中国剩余定理

今有物不知其数,三三数之余二;五五数之余三;七七数之余二。问物几何?

答案: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;
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐