CRT & EXCRT 学习笔记
这玩意解决的是把同余方程组合并的问题。
CRT的核心思想和拉格朗日插值差不多,就是构造一组\(R_i\)使得$\forall i,j(i \neq j) $
\[R_im_i = 1, R_im_j = 0
\]
有了思路后这玩意随便构造一下就出来了,式子里面出现了一些奇怪的逆元,所以要求模数互质
现在考虑扩展CRT,模数不互质了
本质思路是合并两个同余方程组
发现同余条件等价于\(x=k_1m_1+a_1=k_2m_2+a_2\)
怎么求出其中的一个\(k\)呢?其实也就是\(k_1m_1-k_2m_2=a_2-a_1\)
扩展欧几里得即可
Code
#include <cstdio>
#include <iostream>
#define LL long long
using namespace std;
inline LL read() {
LL res = 0, flag = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') flag = 1;
for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch ^ 48);
if(flag) res = ~res + 1;
return res;
}
inline LL gcd(LL x, LL y) {return y ? gcd(y, x % y) : x;}
inline void exgcd(LL a, LL b, LL &x, LL &y) {
if(!b) x = 1, y = 0;
else exgcd(b, a % b, y, x), y -= a / b * x;
}
LL n, a, m, A, M;
int main() {
n = read(), m = read(), a = read();
for(int i = 2; i <= n; ++i) {
M = read(), A = read();
LL d = gcd(m, M), t = A - a, x, y, mod;
if(t % d) return 0;
exgcd(m, M, x, y);
x = t / d * x % (M / d);
if(x < 0) x += M / d;
mod = m / d * M;
a = (x * m + a) % mod;
if(a < 0) a += mod;
m = mod;
}
printf("%lld\n",a);
}