m相互互质:
X被a,b,c处分别余r1,r2,r3。表示为:
X%a = r1
x%b = r2
x%c = r3
bc*k1 % a = 1 ac*k3 % b = 1 ab*k3 % c = 1
所以
x = bc * k1 * r1 + ac * k2 * r2 + ab * k3 * r3
m不相互互质:
假设我们这里有两个方程:
x=a1∗x1+b1
x=a2∗x2+b2
a1,a2是模数,b1,b2是余数。
那么我们可以合并这两个方程:
a1∗x1+b1=a2∗x2+b2
由于x1和x2可以取负无穷到正无穷,所以符号不能约束它们
a1∗x1+a2∗x2=b2−b1扩展欧几里德求出了一个最小正整数解x1
那么令k=(a1∗x1+b1)
x≡k(modlcm(a1,a2))
m相互互质:
int CRT(int a[], int m[], int n) {
int M = 1;
int ans = 0;
for(int i = 1; i <= n; i++) {
M *= m[i];
}
for(int i = 1; i <= n; i++) {
int x, y;
int Mi = M / m[i];
exgcd(Mi, m[i], x, y);
ans = (ans + Mi * x * a[i]) % M;
}
if(ans < 0) ans += M;
return ans;
}
m不相互互质:
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):a;
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b) {x=1;y=0;return a;}
else exgcd(b,a%b,y,x),y-=a/b*x;
}
LL inv(LL a,LL mod)
{
LL x,y;
exgcd(a,mod,x,y);
return (x%mod+mod)%mod;
}
LL exCRT(int k)
{
LL m1,m2,c1,c2,g;
for(int i=2;i<=k;i++)
{
m1=m[i-1],m2=m[i];
c1=c[i-1],c2=c[i];
g=gcd(m1,m2);
if((c2-c1)%g) {flag=0;return -1;}
m[i]=m1*m2/g;
c[i]=inv(m1/g,m2/g)*((c2-c1)/g)%(m2/g)*m1+c1;
c[i]=(c[i]%m[i]+m[i])%m[i];
}
return c[k];
}