Description
给定若干个形如$xequiv a_i pmod {b_i}$的同余方程,其中b不保证两两互质,求最小非负整数解x
Solution
扩展中国剩余定理的模板题。
假定我们已经求出了前k-1个方程的一个解为x
并且记$M=prodlimits_{i=1}^{k-1}{b_i}$
那么前k-1个方程的通解为$x+iM$
考虑当前第k个方程,我们要求出一个t,使得$x+tMequiv 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 ", excrt()); 56 return 0; 57 }