中国剩余定理
中国剩余定理
acwing 204. 表达整数的奇怪方式
题目描述
给定 2n 个整数 a1,a2,…,an 和 m1,m2,…,mn,求一个最小的非负整数 x,满足?i∈[1,n],x≡mi(mod ai)。
输入
第 1 行包含整数 n。
第 2…n+1 行:每 i+1 行包含两个整数 ai 和 mi,数之间用空格隔开。
输出
输出最小非负整数 x,如果 x 不存在,则输出 ?1。
如果存在 x,则数据保证 x 一定在 64 位整数范围内。
数据范围
1≤ai≤231?1,
0≤mi
输入样例:
2
8 7
11 9
输出样例:
31
中国剩余定理
结论
可以发现有个解x=M/m1*n1+M/m2*n2+M/m3*n3+...+M/mi*ni
其中M为mi的乘积,ni是mi的逆元
代码:
#include
using namespace std;
typedef long long LL;
const int N = 15;
int n;
int a[N], m[N];
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;
}
}
int main() {
cin >> n;
LL M = 1;
for (int i = 0; i < n; ++ i) {
cin >> m[i] >> a[i];
M *= m[i]; //读入mi的同时计算M
}
LL res = 0;
for (int i = 0; i < n; ++ i) {
LL Mi = M / m[i]; //计算Mi = M/mi
LL ti, y;
//这一步是求逆元,根据逆元公式的衍生公式可以得到 ti * Mi + y * mi = 1
exgcd(Mi, m[i], ti, y);
res += a[i] * Mi * ti; //计算的同时累加到res中(上述公式里有个sum需要累加)
}
cout << (res % M + M) % M << endl; //对于任意x+kM都是满足要求的解,但目标是输出最小的正整数x,因此取模即可
return 0;
}