中国剩余定理

https://www.luogu.com.cn/problem/P1495

题意概述:给定一组同余方程:

\[x \equiv b_i \pmod {a_i} \]

其中所有 \(a_i\) 互质,求最小正整数解。


考虑构造一组 \(c\),使得 \(c_i\)\(a_i\)\(b_i\),模其他 \(a_j\)\(0\),则 \(x = \sum{c_i}\) 为一个解。
构造方式如下:


令 $d = \prod{a_i} $,则 $c_i = d/a_i \cdot b_i \cdot ((d/a_i)^{-1} \pmod{a_i}) $。
首先因为 \(c_i\)\(d/a_i\) 的因子,模其他 \(a_j\)\(0\) 是显然的;其次 \(d/a_i \cdot ((d/a_i)^{-1} \pmod{a_i})\)\(1\),于是 \(c_i\) 在模 \(a_i\) 意义下为 \(b_i\),因此构造条件满足。


这样得到的 \(x\) 就是满足同余方程的解,\(x\) 在模 \(d\) 意义下的值就是最小整数解。实现上,由于 \(a_i\) 不一定为质数,需要用拓展欧几里得算法求逆元,注意开 i128 和对 \(d\) 取模。


//author:kzssCCC

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;

void solve(){
	int n;
	cin >> n;

	vector<ll> a(n+1),b(n+1);
	ll d = 1;

	for (int i=1;i<=n;i++){
		cin >> a[i] >> b[i];
		d *= a[i];
	}

	auto cal_inv = [&](ll a,ll b){
		ll x,y;

		function<void(ll,ll)> exgcd = [&](ll a,ll b){
			if (b==0){
				x = 1;
				y = 0;
			}
			else{
				exgcd(b,a%b);
				ll tx = x;
				ll ty = y;

				x = y;
				y = tx-a/b*ty;
			}
		};

		exgcd(a,b);

		return (x%b+b)%b;
	};

	ll x = 0;
	for (int i=1;i<=n;i++){
		x = (x+(i128)d/a[i]%d*b[i]%d*cal_inv(d/a[i],a[i])%d)%d; 
	}

	cout << x << '\n';
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int t = 1;
	// cin >> t;
	while (t--) solve();

	return 0;
}
posted @ 2026-04-22 21:11  kzssCCC  阅读(14)  评论(0)    收藏  举报