题目描述:
现有两组数字,每组k个,第一组中的数字分别为:a1,a2,...,ak表示,第二组中的数字分别用b1,b2,...,bk表示。
其中第二组中的数字是两两互素的。求最小的非负整数n,满足对于任意的i,n - ai能被bi整除。
题解:
中国剩余定理模板。
这道题其实就是求n-ai≡0(mod bi)。
根据同余式变换法则,
如果有a≡b(mod m), 则a+c≡b+c(mod m)成立。
所以这道题就变成了求:n≡ai(mod bi),就是——中国剩余定理的模板。
要用快速乘。
但个人比较喜欢写excrt,因为excrt应用范围更广,而且复杂度和crt一样。
不会扩展中国剩余定理模板请移步:
https://www.cnblogs.com/jiangminghong/p/9857305.html
附上代码:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int k; long long ai[20],bi[20]; long long mul(long long x,long long y,long long mod) { long long ans=0; while(y>0) { if(y&1) ans=(ans+x)%mod; x=(x+x)%mod; y>>=1; } return ans; } long long exgcd(long long a,long long b,long long &x,long long &y) { if(b==0) { x=1; y=0; return a; } long long cnt=exgcd(b,a%b,x,y); long long idx=x; x=y; y=idx-a/b*y; return cnt; } long long excrt() { long long x=0,y=0; long long M=bi[1],ans=ai[1]; for(int i=2;i<=k;i++) { long long a=M,b=bi[i],c=((ai[i]-ans)%b+b)%b; long long gcd=exgcd(a,b,x,y),idx=b/gcd; if(c%gcd!=0) return -1; x=mul(x,c/gcd,idx); ans+=x*M; M*=idx; ans=(ans%M+M)%M; } return (ans%M+M)%M; } int main() { scanf("%d",&k); for(int i=1;i<=k;i++) scanf("%lld",&ai[i]); for(int i=1;i<=k;i++) scanf("%lld",&bi[i]); printf("%lld",excrt()); }