中国剩余定理与扩展中国剩余定理
首先来看这个方程
求出上述x的最小正整数解,即为中国剩余定理。
有两种情况,第一种为$b_1$,$b_2$,$b_3$之间两两互质。
第二种情况为不互质时,也就是扩展中国剩余定理
中国剩余定理
设
因为$b_i$之间两两互质,所以M即为他们的最小公倍数。
再设这里的$M_i$与上面的M没有关系。
此时我们得到
这里,$M^{-1}_i$,我们可以用扩展欧几里得求出,也就是$M_i$的数论逆元
左右两边同时乘上$a_i$,得到
参考原方程
得到
然后得到通解
题目链接
代码实现
1 |
|
扩展中国剩余定理
扩展中国剩余定理就是上述的$b_i$不互质的时候。
我们看原方程
设第n个方程的解为x,$M=\prod_{i=1}^n$
那么前k个方程的通解为x+k*m.
把通解带入k+1个方程得到
化简得到
x我们已经求出来的,所以只有一个未知数。
我们需要求的时最小解,所以我们用扩展欧几里得求出k。即可救出下一个方程的x。
若这个方程无解,则整个方程无解。
这就是全部的中国剩余定理
题目链接
代码实现
1 |
|
上述代码已被一组数据hack,有时候会炸long long
5
998244353 469904850
998244389 856550978
998244391 656199240
998244407 51629743
998244431 642142204
下面记录sumijie大佬的代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
typedef __int128 ll;
using namespace std;
void exgcd(ll a,ll b,ll &g,ll &x,ll &y) {
if (b == 0) {
g = a;
x = 1;
y = 0;
return;
}
exgcd(b,a%b,g,y,x);
y-=(a/b)*x;
}
bool flag = false;
ll a1,a2,n1,n2;
ll abs(ll x) {
return x>0?x:-x;
}
void china() {
ll d = a2 - a1;
ll g,x,y;
exgcd(n1,n2,g,x,y);
if (d % g == 0) {
x = ((x*d/g)%(n2/g)+(n2/g))%(n2/g);
a1 = x*n1 + a1;
n1 = (n1*n2)/g;
}
else
flag = true;
}
int n;
long long as[100001];
long long ns[100001];
ll realchina() {
a1 = as[0];
n1 = ns[0];
for (ll i = 1;i<n;i++) {
a2 = as[i];
n2 = ns[i];
china();
if (flag)
return -1;
}
return a1;
}
int main() {
cin>>n;
flag = false;
for (ll i = 0;i<n;i++)
cin>>ns[i]>>as[i];
ll tans = realchina();
}