版权声明:本文为hzy原创文章,未经博主允许不可随意转载。 https://blog.csdn.net/Binary_Heap/article/details/81843440
中国剩余定理总是不太熟练,写一篇 复习一下好了。
中国剩余定理
有 个线性同余方程: , 都互质,求解这个线性同余方程组
使用中国剩余定理( , )来解决,它是一种构造方法,本质思想是每项只对自己有贡献.
令 ,答案为:
其中 表示 , 表示 在 意义下的逆元.
大概写起来是这样的,比较简单
int Crt(int n, int * m, int * a) {
int ans = 0, M = 1;
for(int i = 1; i <= n; i ++) M *= m[i];
for(int i = 1; i <= n; i ++) {
int Mi = M / m[i];
int Ni = inv(Mi, m[i]);
(ans += Mi * Ni % M * a[i] % M) %= M;
}
return (ans + M) % M;
}
扩展中国剩余定理
有 个线性同余方程: ,不保证 都互质,求解这个线性同余方程组
使用扩展中国剩余定理( , )解决, 鸽鸽 称其为增量法.
考虑每次如何把两个线性同余方程合并。
假设有两个方程,
,
由于第一个式子得:
.
于是得到:
然后这是经典的同余方程,直接使用
求解.
解出:
于是得到
于是每次我们两两合并,合并 次,就完事了.
LL exgcd(LL a, LL b, LL &x, LL &y, LL &g) {
if(!b) x = 1, y = 0, g = a;
else exgcd(b, a % b, y, x, g), y -= x * (a / b);
}
LL excrt(int n, LL * m, LL * a) { //x = a[i] (mod m[i])
LL c = a[1], d = m[1], p, q, g;
for(int i = 2; i <= n; i ++) {
exgcd(d, m[i], p, q, g);
LL tmp = a[i] - c;
if(tmp % g != 0) return ; //No result
p *= tmp / g;
p = (p % (m[i] / g) + (m[i] / g)) % (m[i] / g);
c += p * d;
d = d / g * m[i];
c %= d;
}
return (c % d + d) % d;
}