背景概述
今有物不知其数,三三数之剩二;五五数之剩三;七七数之剩二。问物几何?
答曰:二十三。
古人的方法是:三人同行七十稀,五树梅花廿一枝,七子团圆正半月,除百零五便得知。
这句话用算式写下来就是:
23
=
2
∗
70
+
3
∗
21
+
2
∗
15
=
233
,
233
≡
23
(
m
o
d
105
)
23 = 2 * 70 + 3 * 21 + 2 * 15 = 233,233 \equiv 23 (mod 105)
23=2∗70+3∗21+2∗15=233,233≡23(mod105)
这其中的70,21,15是如何得到的呢?
##对上面的进行推论
- x ≡ 1 ( m o d 3 ) y ≡ 0 ( m o d 3 ) z ≡ 0 ( m o d 3 ) x \equiv 1(mod\ 3)\ y \equiv 0(mod\ 3)\ z \equiv 0(mod\ 3) x≡1(mod 3) y≡0(mod 3) z≡0(mod 3)
- x ≡ 0 ( m o d 5 ) y ≡ 1 ( m o d 5 ) z ≡ 0 ( m o d 5 ) x \equiv 0(mod\ 5)\ y \equiv 1(mod\ 5)\ z \equiv 0(mod\ 5) x≡0(mod 5) y≡1(mod 5) z≡0(mod 5)
- x ≡ 0 ( m o d 7 ) y ≡ 0 ( m o d 7 ) z ≡ 1 ( m o d 7 ) x \equiv 0(mod\ 7)\ y \equiv 0(mod\ 7)\ z \equiv 1(mod\ 7) x≡0(mod 7) y≡0(mod 7) z≡1(mod 7)
我们先求解
x
x
x。
不难发现
x
=
35
y
x = 35y
x=35y, 同时有
x
≡
1
(
m
o
d
3
)
,
35
y
≡
1
(
m
o
d
3
)
x \equiv 1(mod\ 3), 35y \equiv 1(mod\ 3)
x≡1(mod 3),35y≡1(mod 3) 得到y = 2也就是求得x = 70。
同样的我们对后面的y, z用同样的方法求解得到分别是21,15。相信我们应该知道中国剩余定理是什么了。
其实整个求解的过程就相当于是求解逆元。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
int a[N], b[N], n;
void exgcd(ll a, ll b, ll &x, ll &y) {
if(!b) {
x = 1;
y = 0;
return ;
}
exgcd(b, a % b, x, y);
ll temp = x;
x = y;
y = temp - a / b * y;
return ;
}
void solve() {
ll m = 1, x, y, ans = 0;
for(int i = 1; i <= n; i++)
m *= b[i];
for(int i = 1; i <= n; i++) {
ll t = m / b[i];
exgcd(t, b[i], x, y);
ans = (ans + x * t * a[i]) % m;
}
ans = (ans + m) % m;
printf("%lld\n", ans);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d %d", &a[i], &b[i]);//a[i]是余数,b[i]是模数。
solve();
return 0;
}