【洛谷P4777】扩展中国剩余定理(Excrt)

Description

给定若干个形如$x\equiv a_i \pmod {b_i}$的同余方程,其中b不保证两两互质,求最小非负整数解x

Solution

扩展中国剩余定理的模板题。

假定我们已经求出了前k-1个方程的一个解为x

并且记$M=\prod\limits_{i=1}^{k-1}{b_i}$

那么前k-1个方程的通解为$x+iM$

考虑当前第k个方程,我们要求出一个t,使得$x+tM\equiv a_k \pmod {b_k}$

变形,得$tM+Nb_k=a_k-x$

这个式子可以用Exgcd求解,若Exgcd有解,那么满足前k个方程的一个解为$x_k=x+tM$

所以我们求解n次扩展欧几里得算法即可得到解,时间复杂度为$O(nlogn)$

Code

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 inline ll read() {
 5     ll ret = 0, op = 1;
 6     char c = getchar();
 7     while (!isdigit(c)) {
 8         if (c == '-') op = -1; 
 9         c = getchar();
10     }
11     while (isdigit(c)) {
12         ret = ret * 10 + c - '0';
13         c = getchar();
14     }
15     return ret * op;
16 }
17 ll mul(ll a, ll b, ll mod) {
18     ll ret = 0;
19     while (b) {
20         if (b & 1) ret = ret + a % mod;
21         a = a + a % mod;
22         b >>= 1;
23     }
24     return ret;
25 }
26 ll exgcd(ll a, ll b, ll &x, ll &y) {
27     if (!b) {
28         x = 1, y = 0;
29         return a;
30     }
31     ll gcd = exgcd(b, a % b, x, y);
32     ll x2 = x, y2 = y;
33     x = y2; 
34     y = x2 - (a / b) * y2;
35     return gcd;
36 }
37 ll ans, a[100010], b[100010], n, M;
38 inline ll excrt() {
39     ans = a[1]; M = b[1];
40     for (register int i = 2; i <= n; ++i) {
41         ll x, y, A = M, B = b[i], C = (a[i] - ans % b[i] + b[i]) % b[i];
42         ll gcd = exgcd(A, B, x, y);
43         x = mul(x, C / gcd, B / gcd);
44         ans += x * M;
45         M *= B / gcd;
46         ans = (ans % M + M) % M;
47     }
48     return (ans % M + M) % M;
49 }
50 int main() {
51     n = read();
52     for (register int i = 1; i <= n; ++i) {
53         b[i] = read(), a[i] = read();
54     }
55     printf("%lld\n", excrt());
56     return 0;
57 }
AC Code

猜你喜欢

转载自www.cnblogs.com/shl-blog/p/11291448.html