2 2 14 57 5 56 5 19 54 40 24 80 11 2 36 20 76
Case 1: 341 Case 2: 5996
题意:
一群鸭子,数数数。。。M个数剩余A个。。求最少有多少鸭子。
解题思路:
中国剩余定理。。但是M不一定互质,所以不能像原来那么求,可以合并所有的方程为一个同余方程,求解一个同余式就可以了。
关键是合并,在网上发现一张图,讲的不错。直接看这个吧!
(n1/d)-1 是(n1/d)的逆。
AC代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <algorithm> using namespace std; typedef long long LL; LL gcd(LL a,LL b) { if(!b)return a; return gcd(b,a%b); } LL exgcd(LL a,LL b,LL &x,LL &y) { if(!b){ x=1;y=0; return a; } LL r=exgcd(b,a%b,x,y); LL t=x; x=y; y=t-(a/b)*y; return r; } LL mod_reverse(LL A,LL B) { LL x,y; LL d=exgcd(A,B,x,y); if(d==1) return (x%B+B)%B; return -1; } LL Merge(LL &A,LL B,LL &mod_A,LL mod_B) { LL C=gcd(mod_A,mod_B); LL d=(B-A); if(d%C) return -1; d=((d/C)%((mod_A*mod_B)/C)+(mod_A*mod_B)/C)%((mod_A*mod_B)/C);//必须取成正整数 LL A1=mod_reverse(mod_A/C,mod_B/C); LL K=A1*d; A=mod_A*K+A; mod_A=(mod_A*mod_B)/C; } LL CRT(LL *M,LL *A,int l) { for(LL i=1;i<l;i++){ if(Merge(A[0],A[i],M[0],M[i])==-1) return -1; } if(A[0]==0) return M[0];//考虑到整除的情况。 LL M1; LL a=1; LL x,y; LL d=exgcd(a,M[0],x,y); if(d==1) return ((x*A[0])%M[0]+M[0])%M[0]; return -1; } int main() { LL t; int xp=1; scanf("%d",&t); while(t--){ int N; LL M[10],A[10]; scanf("%d",&N); for(LL i=0;i<N;i++) scanf("%lld",&M[i]); for(LL i=0;i<N;i++) scanf("%lld",&A[i]); LL res=CRT(M,A,N); if(res==-1) printf("Case %d: -1\n",xp++); else printf("Case %d: %lld\n",xp++,res); } return 0; }