中国剩余定理,又名孙子定理
能求解什么问题呢?
问题:
一堆物品
3个3个分剩2个
5个5个分剩3个
7个7个分剩2个
问这个物品有多少个
解这题,我们需要构造一个答案
我们需要构造这个答案
5*7*inv(5*7, 3) % 3 = 1
3*7*inv(3*7, 5) % 5 = 1
3*5*inv(3*5, 7) % 7 = 1 inv 表示 逆元
然后两边都乘以你需要的数
2 * 5*7*inv(5*7, 3) % 3 = 2
3 * 3*7*inv(3*7, 5) % 5 = 3
2 * 3*5*inv(3*5, 7) % 7 = 2
令
a = 2 * 5*7*inv(5*7, 3)
b = 3 * 3*7*inv(3*7, 5)
c = 2 * 3*5*inv(3*5, 7)
那么
a % 3 = 2
b % 5 = 3
c % 7 = 2
其实答案就是a+b+c
因为
a%5 = a%7 = 0 因为a是5的倍数,也是7的倍数
b%3 = b%7 = 0 因为b是3的倍数,也是7的倍数
c%3 = c%5 = 0 因为c是3的倍数,也是5的倍数
所以
(a + b + c) % 3 = (a % 3) + (b % 3) + (c % 3) = 2 + 0 + 0 = 2
(a + b + c) % 5 = (a % 5) + (b % 5) + (c % 5) = 0 + 3 + 0 = 3
(a + b + c) % 7 = (a % 7) + (b % 7) + (c % 7) = 0 + 0 + 2 = 2
你看你看,答案是不是a+b+c (。・ω・)ノ゙,完全满足题意
但是答案,不只一个,有无穷个,每105个就是一个答案(105 = 3 * 5 * 7)
根据计算,答案等于233,233%105 = 23
如果题目问你最小的那个答案,那就是23了
以下来自百度百科对中国剩余定理的解释 我竟然看明白了
中国剩余定理给出了以下的一元线性同余方程组:
中国剩余定理说明:假设整数m1,m2, ... ,mn两两互质,则对任意的整数:a1,a2, ... ,an,
方程组(S)
有解,并且通解可以用如下方式构造得到:
设
是整数m1,m2, ... ,mn的乘积,并设
是除了mi以外的n- 1个整数的乘积。
设
这个就是逆元了
通解形式为
在模M的意义下,方程组(S)只有一个解:
是不是觉得茅塞顿开??
okk 上模板
代码:
//n个方程:x=a[i](mod m[i]) (0<=i<n)
LL china(int n, LL *a, LL *m){
LL M = 1, ret = 0;
for(int i = 0; i < n; i ++) M *= m[i];
for(int i = 0; i < n; i ++){
LL w = M / m[i];
ret = (ret + w * inv(w, m[i]) * a[i]) % M;
}
return (ret + M) % M;
}
当然,这个中国剩余定理只是基础,面对更强大的敌人,我们要有更强的武器
比如,m1,m2, ... ,mn两两不保证互质,怎么办
别怕,看我接着上模板
代码:
#define LL long long
LL exgcd(LL a,LL b,LL &x,LL &y) {
if(b==0) {
x = 1;
y = 0;
return a;
} else {
LL r = exgcd(b,a%b,y,x);
y -= x*(a/b);
return r;
}
}
//n个方程:x=a[i](mod m[i])
LL CRT(LL *a,LL *m,int n) {
LL c = a[0], l = m[0];
LL d, x, y;
for(int i = 1; i < n; i++) {
d=exgcd(l, m[i], x, y);
if((a[i]-c)%d)
return -1;
x = (a[i] - c) / d * x % (m[i] / d);
c += l * x;
l = l / d * m[i];
c %= l;
}
return c > 0 ? c : c + l; // 如果是求最小非负数 则为return c >= 0 ? c : c + l;
}
推理以及证明
若要了解详情 戳我 我觉得看不懂也没关系 会用就行了
相关题目:
https://blog.csdn.net/henucm/article/details/89398783
https://blog.csdn.net/henucm/article/details/89439529
https://blog.csdn.net/henucm/article/details/89439637
持续更新中~~~