现在的位置: 首页 > 综合 > 正文

2013 ACM/ICPC Asia Regional Changchun Online

2013年10月21日 ⁄ 综合 ⁄ 共 3716字 ⁄ 字号 评论关闭

1004 Cut the Cake http://acm.hdu.edu.cn/showproblem.php?pid=4762 

一个很小的大数。。。解为M/(N^M) ,N、M最大为20,说大不大,说小还不能用long long,一个问题就是约分,所以直接一个一下乘

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000;
long long a[30];
void work (int x)
{
    for(int j=1;j<30;j++)    a[j]*=x;
    for(int j=1;j<30;j++)
    {
        if(a[j]>=10)
        {
            a[j+1]+=a[j]/10;
            a[j]%=10;
        }
    }
}

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}

int main()
{
    int T;cin>>T;
    int n,m;
    while (T--)
    {
        scanf("%d %d",&n,&m);
        memset(a,0,sizeof(a));
        a[1]=1;
        int nn=n;

        int len=m,c;
        int ans=gcd(n,m);
        while (ans!=1)
        {
            m/=ans;
            c=n/ans;
            work(c);
            ans=gcd(n,m);
            len--;
        }
        for(int i=1;i<len;i++)  work(nn);
        int i=29;
        while (a[i]==0) i--;
        printf("%d/",m);
        for(;i>=1;i--)
        {
            printf("%d",a[i]);
        }
        puts("");
    }
    return 0;
}

1005 Theme Section http://acm.hdu.edu.cn/showproblem.php?pid=4763

目测全场最坑题,开始不敢动,想着说用KMP加线段树各种复杂怎么才能做,就搁置了,等过了好多人之后,据说是水题。。。没办法,KMP怒水一下,果断AC,坑的一手好爹!直接KMP,从字符串最后一个的next为最大值往下搜,只要在[Max--Len-Max]之间有一个next的值是Max,那就是它了。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF=0x7fffffff;
const int maxn=1001000;
int p[maxn];
char a[maxn];
int t[maxn*3];

void KMP ()
{
    int l=strlen(a+1);
    int k=0;
    for(int i=2;i<=l;i++)
    {
        while (k>0 && a[1+k]!=a[i])
            k=p[k];
        if(a[k+1]==a[i]) k++;
        p[i]=k;
    }
}

int main()
{
    int T;cin>>T;getchar();
    while (T--)
    {
        memset(p,0,sizeof(p));
        memset(t,0,sizeof(t));
        scanf("%s",a+1);getchar();
        KMP();
        int Max=p[strlen(a+1)];
        int L=strlen(a+1);
        bool flag=false;
        int i,j;
        for(i=Max;i>0;i--)
        {
            if(i>=L-i) continue;
            else{
                for(j=i+1;j<=L-i;j++)
                    if(p[j]==i) {flag=true;break;}
            }
            if(flag) break;
        }
        printf("%d\n",i);
    }
    return 0;
}

1006 Stone http://acm.hdu.edu.cn/showproblem.php?pid=4764

这是签到题,一开始在看别的题,过了二十来分钟才发现它。。。。简单博弈,找必胜态,N-1、N-1-k……

#include <cstdio>
int main()
{
    int n,k;
    while (scanf("%d %d",&n,&k),n||k)
    {
        int b=(n-1)%(k+1);
        if(b==0)
            printf("Jiang\n");
        else
            printf("Tang\n");
    }
    return 0;
}

1010 Flyer http://acm.hdu.edu.cn/showproblem.php?pid=4768

这题最后敲出来了,但没时间debug,不幸挂了。思路是,题目上说要么无解,要么解唯一,所以可以直接从1-INF二分,每次分开的两个区间,如果两个区间的人都是偶数,直接跳出来输出,否则必然是一个区间是奇一个区间是偶,然后一直搜下去,就会找到那个为奇数的人。

代码坑爹啊,先贴我写的挫死代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF=0x7fffffff;
const int maxn=21000;
int N;
struct node
{
    int a,b,c;
}t[maxn];

int work(int L,int R)
{
    int ans=0;
    for(int i=0;i<N;i++)
    {
        if(L>t[i].b) continue;
        if(R<t[i].a) continue;
        if(t[i].a>=L && t[i].b<=R)
            ans+=(t[i].b-t[i].a)/t[i].c+1;
        else if (t[i].a<L && t[i].b<=R)
        {
            if((L-t[i].a)%t[i].c==0)
            {
                ans++;
                ans+=(t[i].b-L)/t[i].c;
            }
            else
            {
                int kk=(L-t[i].a)/t[i].c+1;
                int t2=t[i].a+t[i].c*kk;
                if(t2<=t[i].b)
                {
                    ans++;
                    ans+=(t[i].b-t2)/t[i].c;
                }
            }
        }
        else if (t[i].b>R && t[i].a>=L)
        {
            ans++;
            ans+=(R-t[i].a)/t[i].c;
        }
        else if(t[i].a<=L && t[i].b >=R)
        {
            if((L-t[i].a)%t[i].c==0) ans++;
            int kk=(L-t[i].a)/t[i].c+1;
            int t2=t[i].a+t[i].c*kk;
            if(t2<=R){
                ans++;
                ans+=(R-t2)/t[i].c;
            }
        }
    }
    return ans;
}

int work2 (int x)
{
    int ans=0;
    for(int i=0;i<N;i++)
        if(t[i].a<=x && t[i].b>=x &&(x-t[i].a)%t[i].c==0) ans++;
    return ans;
}

int main()
{
    while (scanf("%d",&N)==1)
    {

        int Max=-INF;
        for(int i=0;i<N;i++){
            scanf("%d %d %d",&t[i].a,&t[i].b,&t[i].c);
            Max=max(Max,t[i].b);
        }
        int L=1,R=INF;
        int x,y;
        x=y=0;
        while (L<R)
        {
            int M=L+(R-L)/2;
            x=work(L,M);
            y=work(M+1,R);
            //printf("L=%d x=%d R=%d y=%d\n",L,x,R,y);
            if(x&1) R=M;
            if(y&1) L=M+1;
            if(x%2==0 && y%2==0) break;
            //if(L==R) break;
        }
        if(L<R) printf("DC Qiang is unhappy.\n");
        else printf("%d %d\n",L,work2(L));
    }
    return 0;
}

下面贴一个北大大牛的代码,提醒我自己代码是有多挫。。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int s[200010],e[200010],d[200010],t,n,i,ans,cnt;
unsigned int l,r,mid;
int main()
{
    while(cin>>n)
    {
        for(i=1;i<=n;i++) scanf("%d%d%d",&s[i],&e[i],&d[i]);
        l=0,r=1ll<<31;
        while(l<r)
        {
            mid=(l+r)>>1;
            ans=0;
            for(i=1;i<=n;i++)
                if(mid>=s[i]) ans+=(min(mid,(unsigned)e[i])-s[i])/d[i]+1;
            if(ans&1) r=mid; else l=mid+1;
        }
        if(l==(1ll<<31)) {puts("DC Qiang is unhappy."); continue;}
        cnt=0;
        for(i=1;i<=n;i++)
            if(l>=s[i]&&l<=e[i]&&(l-s[i])%d[i]==0) cnt++;
        cout<<l<<' '<<cnt<<endl;
    }
    return 0;
}

抱歉!评论已关闭.