扩展中国剩余定理
算法作用
对于给定的一个同余方程组:
x≡c[i](modm[i])
{ x\equiv c[i] \pmod{m[i]}} x≡c[i](modm[i])
初始技巧
1、如何使用扩展欧几里得算法求逆元
2、简单数论
解决方法
第一眼:中国剩余定理!
但是,中国剩余定理需要保证m[i]互质,所以这种方法在这里就逊色了
我们可以采用扩展中国剩余定理(excrt)
我们先从最简单的两个式子入手:
x≡c1(modm1)
{ x\equiv c1 \pmod{m1} }x≡c1(modm1)
x≡c2(modm2) {x\equiv c2 \pmod{m2} } x≡c2(modm2)
变形:
x=k1∗m1+c1 { x=k1*m1+c1 } x=k1∗m1+c1
x=k2∗m2+c2 { x=k2*m2+c2 } x=k2∗m2+c2
联系在一起:
k1∗m1+c1=k2∗m2+c2 {k1*m1+c1=k2*m2+c2} k1∗m1+c1=k2∗m2+c2
k1∗m1=(c2−c1)+k2∗m2 {k1*m1=(c2-c1)+k2*m2} k1∗m1=(c2−c1)+k2∗m2
左右分别除去p=gcd(m1,m2){p=\gcd(m1,m2)}p=gcd(m1,m2)
原式变为:
k1∗m1p=c2−c1p+k2∗m2p {\frac{k1*m1}{p}=\frac{c2-c1}{p}+\frac{k2*m2}{p}} pk1∗m1=pc2−c1+pk2∗m2
k1∗m1p≡c2−c1p(modm2p) {\frac{k1*m1}{p}\equiv \frac{c2-c1}{p} \pmod{\frac{m2}{p}}} pk1∗m1≡pc2−c1(modpm2)
k1≡c2−c1p∗(m1p)−1(modm2p) {k1\equiv \frac{c2-c1}{p}*(\frac{m1}{p})^{-1} \pmod{\frac{m2}{p}}} k1≡pc2−c1∗(pm1)−1(modpm2)
k1=c2−c1p∗(m1p)−1(modm2p)+k3∗m2p {k1= \frac{c2-c1}{p}*(\frac{m1}{p})^{-1} \pmod{\frac{m2}{p}}} +k3*\frac{m2}{p}k1=pc2−c1∗(pm1)−1(modpm2)+k3∗pm2
我们可以将k1带回原来的x中,得到:
x=(c2−c1p∗(m1p)−1(modm2p)+k3∗m2p)∗m1+c1 x=(\frac{c2-c1}{p}*(\frac{m1}{p})^{-1} \pmod{\frac{m2}{p}} +k3*\frac{m2}{p})*m1+c1 x=(pc2−c1∗(pm1)−1(modpm2)+k3∗pm2)∗m1+c1
x=c2−c1p∗(m1p)−1∗m1(modm2p)+k3∗m2p∗m1+c1 x=\frac{c2-c1}{p}*(\frac{m1}{p})^{-1}*m1 \pmod{\frac{m2}{p}} +k3*\frac{m2}{p}*m1+c1 x=pc2−c1∗(pm1)−1∗m1(modpm2)+k3∗pm2∗m1+c1
x≡c2−c1p∗(m1p)−1∗m1(modm2p)+c1(mod(m2p∗m1)) x\equiv \frac{c2-c1}{p}*(\frac{m1}{p})^{-1}*m1 \pmod{\frac{m2}{p}} +c1 \pmod{(\frac{m2}{p}*m1)}x≡pc2−c1∗(pm1)−1∗m1(modpm2)+c1(mod(pm2∗m1))
由于m1,m2,c2,c1都是已知的。
所以这个式子是可求的。
我们再令
m=m2p∗m1 m=\frac{m2}{p}*m1 m=pm2∗m1
c=c2−c1p∗(m1p)−1∗m1(modm2p)+c1 c= \frac{c2-c1}{p}*(\frac{m1}{p})^{-1}*m1 \pmod{\frac{m2}{p}} +c1 c=pc2−c1∗(pm1)−1∗m1(modpm2)+c1
于是乎,我们就有了新的同余式:
x≡c(modm) x\equiv c \pmod m x≡c(modm)
再将新求出来的c与m带入原来的c1与m1中,再逐个合并就好了。
全部的c[i]与m[i]合并成一个同余式后,明显,答案就是c mod m了。
代码
#include<cstdio>
#define N 1001
using namespace std;
long long m[N],c[N];
int n;
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 p=exgcd(b,a%b,x,y);
long long t=x;x=y;
y=t-(a/b)*y;return p;
}
long long niyuan(long long x,long long y)
{
long long xx=0,yy=0;
long long p=exgcd(x,y,xx,yy);
while (xx<0) xx+=y;
return xx;
}
int excrt()
{
long long m1=m[1],c1=c[1];
for (int i=2;i<=n;i++)
{
long long m2=m[i],c2=c[i];
long long unless1,unless2;
long long gcdm=exgcd(m1,m2,unless1,unless2);
if ((c2-c1)%gcdm!=0) return -1;
long long newm=m1*m2/gcdm;
long long newc=niyuan(m1/gcdm,m2/gcdm)*((c2-c1)/gcdm)%(m2/gcdm)*m1+c1;
m1=newm;c1=newc;
while (c1<0) c1=(c1+m1)%m1;
}
return c1%m1;
}
int main()
{
freopen("excrt.in","r",stdin);
freopen("excrt.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lld%lld\n",&m[i],&c[i]);
long long ans=excrt();
printf("%lld\n",ans);
}


888

被折叠的 条评论
为什么被折叠?



