hdu3579 Hello Kiki(数论)
用到中国剩余定理,然后用扩展欧几里得算法求解。
这里有两个注意点,1、硬币数量不能为0或者负数
2、每个group数量有可能大于50,样例中就有
#include<stdio.h> #include<math.h> #include<stdlib.h> int M[10],A[10],n; int extEuclid(int p,int q,int &x,int &y)//扩展欧几里得算法 { int d,tmp; if(q==0){x=1;y=0;return p;} d=extEuclid(q,p%q,x,y); tmp=x;x=y;y=tmp-p/q*y; return d;//返回最大公约数 } int calcu(int cur) { int x,y,g,t; int a1=M[cur-1],a2=M[cur]; int b1=A[cur-1],b2=A[cur]; g=extEuclid(a1,a2,x,y); int s=b2-b1; if(s%g) return -1; else { t=a2/g; x=x*s/g;//这个一定要放在“x=(x%t+t)%t”前面,否则就wa了 x=(x%t+t)%t;//求出在0~t之间的一个解。这一步必须有,否则就wa,因为爆int了,可改成long long,改过后也可以ac a2=a1*a2/g; s=((a1*x+b1)%a2+a2)%a2; A[cur]=s; M[cur]=a2; if(cur==n-1) { if(s==0) return M[cur]; else return A[cur]; } else return calcu(cur+1); } } int main() { int i,j,k,t; scanf("%d",&t); for(k=1;k<=t;k++) { scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&M[i]); for(i=0;i<n;i++) scanf("%d",&A[i]); printf("Case %d: ",k); if(n==1) { if(A[0]==0) A[0]=M[0]; printf("%d\n",A[0]); continue; } printf("%d\n",calcu(1)); } return 0; }