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);
} 
posted @ 2022-03-22 16:14  DCH233  阅读(42)  评论(0编辑  收藏  举报