题解 P4777 【【模板】扩展中国剩余定理(EXCRT)】
注意一下::
题目是
我总是习惯性的把a和b交换位置,调了好久没调出来,
本题解是按照
x≡a_i\pmod {b_i}
讲述的,请注意
本题
说是扩展中国剩余定理,其实好像和中国剩余定理关系不大。
使用数学归纳法,如果我们已经知道了前
然后
综上,循环
讲一下如何用扩展欧几里德解线性同余方程。
大家都知道(假设大家都知道),
的一组整数解。 我们要解的线性同余方程是这样的:
可以写成这个形式:
若方程有解,则
一定成立。题目保证有解,无需特判。
于是我们用扩欧求出
的一组解,然后等式两边同时除以
得解。
还有个细节,就是乘的时候会爆long long,而__int128这个东西比赛时是不可用的,所以还是老老实实打快
ll Slow_Mul(ll n, ll k, ll mod){
ll ans = 0;
while(k){
if(k & 1) ans = (ans + n) % mod;
k >>= 1;
n = (n + n) % mod;
}
return ans;
}
完整
#include <cstdio>
const int MAXN = 100010;
typedef long long ll;
int n;
ll a[MAXN], b[MAXN], ans, M, x, y;
ll exgcd(ll a, ll b, ll &x, ll &y){
if(!b){ x = 1; y = 0; return a; }
ll d = exgcd(b, a % b, x, y);
ll z = x; x = y; y = z - (a / b) * y;
return d;
}
ll Slow_Mul(ll n, ll k, ll mod){
ll ans = 0;
while(k){
if(k & 1) ans = (ans + n) % mod;
k >>= 1;
n = (n + n) % mod;
}
return ans;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%lld%lld", &b[i], &a[i]);
ans = a[1];
M = b[1];
for(int i = 2; i <= n; ++i){
ll B = ((a[i] - ans) % b[i] + b[i]) % b[i];
ll GCD = exgcd(M, b[i], x, y);
x = Slow_Mul(x, B / GCD, b[i]);
ans += M * x;
M *= b[i] / GCD;
ans = (ans + M) % M;
}
printf("%lld\n", ans);
return 0;
}