拓展中国剩余定理
•拓展中国剩余定理
拓展中国剩余定理是用来解同余方程
$egin{cases}xequiv c_{1}left( mod m_{1} ight) \ xequiv c_{2}left( mod m_{2} ight) \ ldots \ xequiv c_nleft( mod m_n ight) end{cases}$
ps.如果m1,m2,m3...mn两两互素的话,可以用中国剩余定理来求
•过程
假设
$xequiv c_{1} (mod m_{1})$ ①
$xequiv c_{1} (mod m_{2})$ ②
则
$x=c_{1}+m_{1}k_{1}$ ③
$x=c_{2}+m_{1}k_{2}$ ④
③=④得 $m_{1}k_{1}=c_{2}-c_{1}+m_{2}k_{2}$ ⑤
设$t=gcd(m1,m2)$
⑤ 两边同时除以t 得
$frac{m_{1}k_{1}}{t}=frac{c_{2}-c_{1}}{t}+frac{m_{2}k_{2}}{t}$ ⑥
⑥ $mod frac{m_{2}}{t}$得
$k_{1}frac{m_{1}}{t}equiv frac{c_{2}-c_{1}}{t}(mod frac{m_{2}}{t})$ ⑦
则$k_{1}=inv(frac{m_{1}}{t},frac{m_{2}}{t})cdot frac{c_{2}-c_{1}}{t}+frac{m_{2}}{t}cdot y$⑧
将⑧代入①
$x=inv(frac{m_{1}}{t},frac{m_{2}}{t})cdot frac{c_{2}-c_{1}}{t}cdot m_{1}+frac{m_{1}m_{2}}{t}y+c_{1}$
则$xequiv inv(frac{m_{1}}{t},frac{m_{2}}{t})cdot frac{c_{2}-c_{1}}{t}cdot m_{1}+c_{1}(mod frac{m_{1}m_{2}}{t})$
可以看出,x的值与$frac{c_{2}-c_{1}}{t}$有关
所以,当$(c_{2}-c_{1})|gcd(m_{1},m_{2})$时,x有解
若化成 $xequiv c (mod m)$
则$m=frac{m_{1}m_{2}}{t}$
$c=inv(frac{m_{1}}{t},frac{m_{2}}{t})cdot frac{c_{2}-c_{1}}{t}$%$frac{m_{2}}{t}cdot m_{1}+c_{1}$
•结论
通过中国剩余定理可以把两个同余式转化成一个新的同余式式
那推广一下n个同余式合并,
两个同余式求解之后得到一个新的同余式
再把新的同余式和其他的联立
最终就可以求出满足条件的解
•模板
View Code1 #include<cstdio> 2 using namespace std; 3 typedef long long ll; 4 ll n; 5 ll a[100010],b[100010]; 6 ll mul(ll A,ll B,ll mod) //快速乘取余 模板 7 { 8 ll ans=0; 9 while(B>0) 10 { 11 if(B & 1) ans=(ans+A%mod)%mod; 12 A=(A+A)%mod; 13 B>>=1; 14 } 15 return ans; 16 } 17 ll exgcd(ll A,ll B,ll &x,ll &y) //扩展欧几里得 模板 18 { 19 if(!B) 20 { 21 x=1,y=0; 22 return A; 23 } 24 ll d=exgcd(B,A%B,x,y); 25 ll tmp=x; 26 x=y , y=tmp-A/B*y; 27 return d; 28 } 29 ll lcm(ll A,ll B) //求最小公倍数 30 { 31 ll xxx,yyy; 32 ll g=exgcd(A,B,xxx,yyy); 33 return (A/g*B); 34 } 35 ll excrt() //重点:求解同余方程组 36 { 37 ll x,y; 38 ll M=b[1],ans=a[1]; //赋初值 39 //M为前k-1个数的最小公倍数,ans为前k-1个方程的通解 40 for(int i=2;i<=n;i++) 41 { 42 ll A=M,B=b[i]; 43 ll C=(a[i]-ans%B+B)%B; //代表同余方程 ax≡c(mod b) 中a,b,c 44 45 ll g=exgcd(A,B,x,y); 46 //求得A,B的最大公约数,与同余方程ax≡gcd(a,b)(mod b)的解, 47 48 if(C%g) return -1; //无解的情况 49 50 x=mul(x,C/g,B); //求得x的值,x即t 51 ans+=x*M; //获得前k个方程的通解 52 M=lcm(M,B); //更改M的值 53 ans=(ans%M+M)%M; 54 } 55 return ans; 56 } 57 int main() 58 { 59 scanf("%lld",&n); 60 for(int i=1;i<=n;i++) 61 scanf("%lld%lld",&b[i],&a[i]); 62 ll ans=excrt(); 63 printf("%lld",ans); 64 }