搞搞中国剩余定理和它的扩展
Posted tongseli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搞搞中国剩余定理和它的扩展相关的知识,希望对你有一定的参考价值。
中国剩余定理
解决同余方程组的相关问题,然而貌似扩展一下发生质变?
同余方程组问题
\[x\equiv a_1 \mod m_1 \]
\[x\equiv a_2 \mod m_2 \]
\[\dots\dots\]
\[x\equiv a_n \mod m_n \]
求解满足上述同余方程组的\(x\)
中国剩余定理(CRT)
- 要求:模数\(m_1,m_2,\dots,m_n\) 必须互质(为什么呢?)
- CRT告诉我们,这个方程组在模\(M=m_1*m_2*\dots*m_n\) 意义下的解是唯一的。
- CRT还告诉我们这个解为\[x\equiv a_1 M_1 M_1^-1+a_2 M_2M_2^-1+\dots+a_n M_nM_n^-1 \mod M\]其中\(M_i=M/m_i\) ,而\(M_i^-1\) 是模\(m_i\) 意义下的逆元。
- \[x=\sum a_i\fracMm_iinv(\fracMm_i,\,m_i)\]
- 这个解是构造性的解,可以验证其是满足上述方程组的。
- 为什么两两互质?逆元的要求!
const int maxn=1000;
int a[maxn];
int m[maxn];
int CRT(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+a[i]*Mi*x)%M;
if(ans<0)ans+=M;
return ans;
扩展中国剩余定理(exCRT)
- 模数\(m_1,m_2,\dots,m_n\) 不互质的时候也可以有解啦!
- 考虑一下同余方程组仅有两个方程的情况。
- \[x\equiv c_1 \mod m_1 \] ,\[x\equiv c_2 \mod m_2\]
- \[x=c_1 +m_1k_1$ ,$x=c_2 +m_2k_2\]
- \[c_1 +m_1k_1=c_2 +m_2k_2\]
- \[m_1k_1 =c_2-c_1+m_2k_2\]
- 这个方程有解的充要条件是\[\gcd(m_1,m_2)\,|\,(c_2-c_1)\]
- \[\fracm_1k_1\gcd(m_1,m_2) =\fracc_2-c_1\gcd(m_1,m_2)+\fracm_2k_2\gcd(m_1,m_2)\]
- \[\fracm_1k_1\gcd(m_1,m_2) \equiv\fracc_2-c_1\gcd(m_1,m_2)\mod \fracm_2\gcd(m_1,m_2)\]
- \[k_1\equiv inv(\fracm_1\gcd(m_1,m_2),\fracm_2\gcd(m_1,m_2))*\fracc_2-c_1\gcd(m_1,m_2)\mod \fracm_2\gcd(m_1,m_2)\]
- \(inv(a,b)\) 表示\(a\) 在模\(b\) 意义下的逆元
- \[k_1=inv(\fracm_1\gcd(m_1,m_2),\fracm_2\gcd(m_1,m_2))*\fracc_2-c_1\gcd(m_1,m_2)+K* \fracm_2\gcd(m_1,m_2)\]
- 带回\(x=c_1 +m_1k_1\)
- \[x=c_1 +m_1*(inv(\fracm_1\gcd(m_1,m_2),\fracm_2\gcd(m_1,m_2))*\fracc_2-c_1\gcd(m_1,m_2)+K* \fracm_2\gcd(m_1,m_2))\]
- \[x\equiv c_1 +m_1*inv(\fracm_1\gcd(m_1,m_2),\fracm_2\gcd(m_1,m_2))*\fracc_2-c_1\gcd(m_1,m_2)\mod \fracm_1m_2\gcd(m_1,m_2)\]
- 到这里,我们已经完成了两个同余方程的整合!有形式\(x\equiv a \mod m\)
- 其中\[a=c_1 +m_1*inv(\fracm_1\gcd(m_1,m_2),\fracm_2\gcd(m_1,m_2))*\fracc_2-c_1\gcd(m_1,m_2)\] \[m=\fracm_1m_2\gcd(m_1,m_2)\]
- 反复重复以上操作!(二合一,加一,合一,······)
const int maxn=1000;
int a[maxn];
int m[maxn];
int gcd(int a,int b)
return b?gcd(b,a%b):a;
int exgcd(int a,int b, int &x,int &y)
if(b==0)
x=1;
y=0;
return a;
int d=exgcd(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-a/b*y;
return d;
int inv(int a,int mod)
int x,y;
int d=exgcd(a,mod,x,y);
return d==1?(x%mod+mod)%mod:-1;
int exCRT(int n)
int m1, m2, c1, c2, d;
for(int i=2;i<=n;i++)
m1=m[i-1];//这里是与前一个进行合并
m2=m[i];
c1=a[i-1];
c2=a[i];
d=gcd(m1,m2);
if((c2-c1)%d!=0)
return -1;//无法合并
m[i]=m[i-1]*m[i]/d;//公式(倒数第二个)
a[i]=c1+m1*inv(m1/d,m2/d)%(m2/d)*(c2-c1)/d;//公式(倒数第二个)
a[i]=(a[i]%m[i]+m[i])%m[i];
return a[n];
以上是关于搞搞中国剩余定理和它的扩展的主要内容,如果未能解决你的问题,请参考以下文章