CRT & EXCRT 學習筆記
阿新 • • 發佈:2022-03-22
這玩意解決的是把同餘方程組合並的問題。
CRT的核心思想和拉格朗日插值差不多,就是構造一組\(R_i\)使得$\forall i,j(i \neq j) $
有了思路後這玩意隨便構造一下就出來了,式子裡面出現了一些奇怪的逆元,所以要求模數互質
現在考慮擴充套件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); }