中国剩余定理
中国剩余定理
今有物不知其数,三三数之余二;五五数之余三;七七数之余二。问物几何?
答案:23
口诀:三人同行七十稀,五树梅花廿一枝,七子团圆月正半,除百零五便得知
其实原问题就是求解以下的同余方程组
{x≡2 (mod 3)x≡3 (mod 5)x≡2 (mod 7)
\left\{
\begin{aligned}
x \equiv 2 \, (mod \,\, 3) \\
x \equiv 3 \, (mod \,\, 5) \\
x \equiv 2 \, (mod \,\, 7)
\end{aligned}
\right.
⎩⎪⎨⎪⎧x≡2(mod3)x≡3(mod5)x≡2(mod7)
而 23=(2×70+3×21+2×15) mod (3×5× 7)23 = (2 \times 70 + 3 \times 21 + 2 \times 15) \,\, mod \,\,(3 \times 5 \times\ 7)23=(2×70+3×21+2×15)mod(3×5× 7),那70,21,1570,21,1570,21,15是怎么求得的呢,通过以下三步:
- 707070实际上是555和777的公倍数中模333余111的最小的那个数,x≡1 (mod 3)x \equiv 1 \,(mod\,\,3)x≡1(mod3),其中x=35kx = 35kx=35k
- 212121实际上是333和777的公倍数中模555余111的最小的那个数,x≡1 (mod 5)x \equiv 1\, (mod \,\,5)x≡1(mod5),其中x=21kx = 21kx=21k
- 151515实际上是333和555的公倍数中模777余111的最小的那个数,x≡1 (mod 7)x \equiv 1 \,(mod\,\,7)x≡1(mod7),其中x=15kx = 15kx=15k
其中有什么原理呢?
首先假设x1x_1x1是x≡2 (mod 3)x \equiv 2 \, (mod \,\, 3)x≡2(mod3)的解,x2x_2x2是x≡3 (mod 5)x \equiv 3 \, (mod \,\, 5)x≡3(mod5)的解,x3x_3x3是x≡2 (mod 7)x \equiv 2 \, (mod \,\, 7)x≡2(mod7)的解
那么能否进一步满足,x1+x2x_1+x_2x1+x2模333余222也成立呢?只要满足**x2x_2x2是333的倍数就可以,同理要使得x1+x3x_1+x_3x1+x3模333余222也成立,那么x3x_3x3也得是333的倍数**,这是从x1x_1x1的角度出发
来看x2x_2x2,x2x_2x2满足模555余333成立。为了使得x1+x2x_1+x_2x1+x2也满足模555余333成立,那么x1x_1x1必须是555的倍数,同理,x3x_3x3也要是555的倍数,才能满足x2+x3x_2+x_3x2+x3模555余333成立。
最后是x3x_3x3。同理**x1,x2x_1,x_2x1,x2也必须是777的倍数**。弄清楚了这些条件
那么x1+x2+x3x_1+x_2+x_3x1+x2+x3就是最终的一个答案了。总的来说这333个数要满足
- x1x_1x1模333余数是222,同时x1x_1x1是555和777的一个公倍数
- x2x_2x2模555余数是333,同时x2x_2x2是333和777的一个公倍数
- x3x_3x3模777余数是222,同时x3x_3x3是333和555的一个公倍数
需要注意的是,x1+x2+x3x_1+x_2+x_3x1+x2+x3只是其中一个解,并不是最小的解。要明白如果ttt是上述同余方程组的解那么t+105kt+105kt+105k也是方程组的解。105105105是3,5,73,5,73,5,7的最小公倍数
求解的时候,可以使用扩展欧几里德算法,将x1x_1x1模333余数是222,变成x1x_1x1模333余数是111,将答案乘以222即可,相当于求x1−3k=1x1 - 3k = 1x1−3k=1
例题:
给定 nnn 组非负整数 ai,bia_i, b_iai,bi ,求解关于 xxx 的方程组的最小非负整数解。(其中aia_iai两两互质)
{x≡b1 (mod a1)x≡b2 (mod a2)................x≡bn (mod an)
\left\{
\begin{aligned}
x \equiv b_1 \, (mod \,\, a_1) \\
x \equiv b_2 \, (mod \,\, a_2) \\
................\\
x \equiv b_n \, (mod \,\, a_n)
\end{aligned}
\right.
⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧x≡b1(moda1)x≡b2(moda2)................x≡bn(modan)
输入
输入第一行包含整数 nnn。
接下来 nnn 行,每行两个非负整数 ai,bia_i, b_iai,bi。
输出
输出一行,为满足条件的最小非负整数 xxx。
输入样例
3
2 1
3 2
5 3
输出样例
23
代码
#include <cstdio>
#include <iostream>
#define N 100005
#define ll long long
using namespace std;
ll a[N], b[N], M = 1;
int n;
void ex_gcd (ll a, ll b, ll &x, ll & y) { //扩展欧几里德
if (!b) {
x = 1, y = 0;
return ;
}
ex_gcd(b, a%b, x, y);
ll t = x;
x = y;
y = t - a / b * y;
}
ll CRT () {
ll ans = 0, x, y, g;
for (int i = 1; i <= n; i++)
M *= a[i];
for (int i = 1; i <= n; i++) {
ex_gcd (M / a[i], a[i], x, y);
ans = (ans + x * (M / a[i]) * b[i]) % M;
}
return (ans + M) % M;
}
int main () {
scanf ("%d", &n);
for (int i = 1; i <= n; i++)
scanf ("%lld %lld", &a[i], &b[i]);
printf("%lld\n", CRT ());
return 0;
}
更多推荐


所有评论(0)