扩展CRT学习笔记
中国剩余定理是用来解同余方程组的
${x} \equiv {r_1} (mod \;p_1)$
${x} \equiv {r_2} (mod \;p_2)$
$...$
${x} \equiv {r_n} (mod \;p_n)$
但是构造法只能求解$p$都互质的情况,那当$p$不互质怎么办办勒把出题人吊起来打一顿就好了
然而NOI时好像不能跑出考场阿掉出题人啊~~~
那我们可以考虑两个同余方程
${x} \equiv {r_1} (mod \;p_1)$
${x} \equiv {r_2} (mod \;p_2)$
我们试图把它们合并成一个,如果成功了,我们就可以把n个方程合并成一个,然后就可以出解啦
怎么合并勒?
发现$x=r_1+k_1*p_1=r_2+k_2*p_2$
那么${k_1*p_1}\equiv{r_2-r_1}(mod\;p_2)$
那么把等式全除以$gcd(p_1,p_2)$,当$r_2-r_1$不能被整除时,就无解了
否则我们把$p_1$和$p_2$都除以$gcd(p_1,p_2)$后就互质了,就可以求逆元啦,然后就可以求出$k_1$啦
那么新的方程就是${x} \equiv {r_1+k_1*p_1} (mod \;\frac{(p_1)(p_2)}{(gcd(p_1,p_2)})$
我的模板(由于种种原因,我加了龟速快速乘防止爆long long)
#include<bits/stdc++.h> using namespace std; #define int long long int n,i,j,a[500000],b[500000]; int gcd(int a,int b) { return b?gcd(b,a%b):a; } int exgcd(int a,int b,int &x,int &y) { int t=a; if(!b)x=1,y=0;else t=exgcd(b,a%b,y,x),y-=(a/b)*x; return t; } int mul(int a,int b,int mod) { a%=mod,b%=mod; a=(a+mod)%mod,b=(b+mod)%mod; int ans=0; while(b) { if(b%2)ans=(ans+a)%mod; a=a*2%mod;b=b/2; } return ans; } int CRT(int *re,int *mod,int n) { int r=0,m=1; for(int i=0;i<n;i++) { int g=gcd(m,mod[i]),x,y; if((re[i]-r)%g)return -1; int inv;exgcd(m/g,mod[i]/g,x,y);inv=x; int M=m/gcd(m,mod[i])*mod[i]; int k1=mul((re[i]-r)/g,inv,M); r+=mul(k1,m,M); m=M;r=(r+m)%m; } return r; } main() { scanf("%lld",&n); for(i=1;i<=n;i++)scanf("%lld%lld",&a[i],&b[i]); printf("%lld",CRT(b+1,a+1,n)); return 0; }