目录
拓展中国剩余定理(exCRT)
给定 (n) 组整数 (a_i,b_i) 求解非负最小/某区间内的整数 (x) 使得
(egin{cases} xequiv a_1(mod b_1) \ \ xequiv a_2(mod b_2) \ \ xequiv a_3(mod b_3) \ \ ...... \ \ xequiv a_n(mod b_n) end{cases})
数据保证有解
我们先考虑一个子问题:
如果已知 (egin{cases} xequiv a_1(mod b_1) \ \ xequiv a_2(mod b_2) end{cases}) 那怎么表示所有满足条件的整数 (x) 呢?
由第一个方程可知: (x=a_1+tcdot b_1,tin Z)
因此,我们代入第二个方程:
(a_1+tcdot b_1equiv a_2(mod b_2))
显然得到:
(tcdot b_1equiv a_2-a_1(mod b_2))
由拓展欧几里得算法(exGCD)可以求解 (tb_1+mb_2=a_2-a_1) 的 (t,m)
因此,保证有解的情况下, (t) 一定是可求的
最后我们求出 (x=a_1+tcdot b_1) 是其中的一个解
而对于其余解 (x'=a+tcdot b_1+kcdot lcm(b_1,b_2),kin Z) 显然也是符合上述的解
即归纳起来:
(xequiv a_1+tcdot b_1(mod lcm(b_1,b_2) ))
回归正题,如果两个同余方程组可以如上求解,则 (n) 个方程的方程组显然可以:先用上述方法将 1.2 合并,变成 ((n-1)) 个方程组;再将剩下的 1.2 合并,变成 ((n-2)) 个方程组;以此类推,最后可以合并为一个方程组:
(displaystyle xequiv a(mod ext{lcm}_{i=1}^n b_i))
当然,对于原方程组,我们加入 (xequiv 0(mod 1)) 也是允许的,因此,我们可以用这个作为初始条件:
int exgcd(int a,int b,int &x,int &y){
...
}
void excrt(int &a1,int &b1,int a2,int b2){
int t,m,g=exgcd(b1,b2,t,m);
t*=a2-a1;
a1=a1+t*b1;
b1=b1/g*b2;
a1=(a1%b1+b1)%b1;
}
...
int a=0,b=1;
for(int i=1;i<=n;i++){
int tmpa=read(),tmpb=read();
excrt(a,b,tmpa,tmpb);
}