Skip to content

中国剩余定理

cpp
template <class T>
i64 crt(std::span<const T> a, std::span<const T> m) {
	assert(a.size() == m.size());
	i64 prod = 1, ret = 0;
	for (auto mi : m)
		prod *= mi;
	for (int i = 0; i < a.size(); ++i) {
		i64 u = prod / m[i], v = inv_gcd(u, m[i]);
		ret = (ret + a[i] * u * v) % prod;
	}
	return ret;
}

扩展中国剩余定理

cpp
template <class T>
i64 excrt(std::span<const T> a, std::span<const T> m) {
	assert(a.size() == m.size());
	i64 ans = a[0], M = m[0];
	for (int i = 0; i < a.size(); ++i) {
		i64 ai = a[i], mi = m[i];
		if (M % mi == 0 && ans % mi == a)
			continue;
		i64 B = (ai - ans % mi + mi) % mi;
		auto [x, y, g] = exgcd(M, mi);
		if (B % g != 0)
			return -1;
		x = i128(x) * (B / g) % (mi / g);
		ans += M * x, M *= mi / g;
		ans = (ans + M) % M;
	}
	return ans;
}