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;
}