中南大学第七届大学生程序设计竞赛

来源:互联网 发布:淘宝店铺花呗 编辑:程序博客网 时间:2024/09/21 06:38

Balls and Boxes

拓展欧几里德的应用,比赛时看到题目就想到拓展欧几里德了,不过由于少了一个判断条件Wrong了,而且中南的oj还不能用I64输出。

赛后看了题解,加了个条件,一开始很天真的用while循环累加,果断超时,没办法了,只能精确推出倍数,结果又Wrong了。

经过n次试验,无节操的提交终于找到问题的根源了,由于推出来的公式次数是负的,调用Exgcd的时候直接带入的-n,导致求出来的(m,n)<0,结果累加量也小于零。

总的来说,题目不难,但是需要注意的细节比较多,谨记谨记!


Happy Number

第一次写数位DP,之前看了一篇国家队的论文,写起来很顺手,做之前题目的时候发现不能用I64输出,做这个题目在Wrong了十次左右之后发现输入也不能用I64d。


Balls and Boxes ACcode:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;typedef long long LL;int Exgcd(int a, int b, LL &x, LL &y){    if (b == 0)    {        x = 1,y = 0;        return a;    }    int r = Exgcd(b, a % b, x, y);    LL t = x;    x = y;    y = t - a / b * y;    return r;}int Max(int a1,int a2){    return a1>a2?a1:a2;}int Min(int a1,int a2){    return a1<a2?a1:a2;}int main(){    int m,n,s,T,d,up,down;    LL ans,x,y,a,b,t,cnt;    scanf("%d",&T);    while (T--)    {        cnt=s=0,up=-1,down=10000007;        scanf("%d%d",&m,&n);        for (int i=0;i<m;i++)        {            scanf("%d",&d);            up=Max(up,d);            down=Min(down,d);            s+=d;        }        d=Exgcd(m,n,y,x);        if (down==up) ans=0;        else if (s%d) ans=-1;        else        {           x*=-s/d,y*=s/d;           a=m/d,b=n/d;           if (y>=up) t=(y-up)/b;           else t=(y-up+1)/b-1;           y-=t*b,x-=t*a;           if ((y-x)>down)           {               t=(y-x-down-1)/(a-b)+1;               x+=t*a,y+=t*b;           }           ans=x;        }        printf("%lld\n",ans);    }    return 0;}


Happy Number ACcode:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;typedef long long LL;LL a,b,res;int up[20];int y[1600],vis[1600];LL f[20][1600],dp[1600];int pow2(LL x){    int s=0,t;    while (x>0)    {        t=x%10;        s+=t*t;        x/=10;    }    return s;}void prepare(){    int t,k,s;    int x[]={1,7,10,13,19,23,28,31,32,44,49};    up[1]=81;    memset(f,0,sizeof(f));    memset(vis,0,sizeof(vis));    for (int i=0;i<=10;i++) vis[x[i]]=1;    for (int i=50;i<1600;i++)    {        k=i;        while (k>=i) k=pow2(k);        vis[i]=vis[k];    }    for (int i=0;i<10;i++)    f[1][i*i]=1;    for (int i=2;i<19;i++)    {        for (int j=0;j<10;j++)        {            t=j*j;            for (int k=up[i-1];k>=0;k--)            f[i][k+t]+=f[i-1][k];        }        up[i]=up[i-1]+81;    }}void dfs(int pre,LL num){    if (num<10)    {        for (int j=0;j<=num;j++)        {            int t=pre+j*j;            if (vis[t]) dp[t]++;        }        return ;    }    int d=0,p;    LL t=num,r=1,c=0;    while (t>9)    {        d++;        c+=(t%10)*r;        r*=10;        t/=10;    }    for (int i=0;i<t;i++)    {        p=pre+i*i;        for (int j=up[d];j>=0;j--)        dp[j+p]+=f[d][j];    }    pre+=t*t;    dfs(pre,c);}LL solve(LL num){    memset(dp,0,sizeof(dp));    dfs(0,num);    LL sum=0;    for (int i=1;i<1500;i++)        if (vis[i]) sum+=dp[i];    return sum;}int main(){    prepare();    int T;    scanf("%d",&T);    while (T--)    {        scanf("%lld%lld",&a,&b);        LL res=solve(b);        res-=solve(a-1);        if (res<0) res=-1;        printf("%lld\n",res);    }    return 0;}