题目
给定 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<ai
1≤n≤25
输入样例:
2
8 7
11 9
输出样例:
31
解析:
代码
#include <iostream>
using namespace std;
typedef long long LL;
LL exgcd(LL a, LL b, LL &x, LL &y){
if(!b){
x = 1, y = 0;
return a;
}
LL d = exgcd(b, a%b, y, x);
y -= a/b * x;
return d;
}
int main()
{
int n;
cin >> n;
LL a1, m1;
cin >> a1 >> m1;
bool flag = true;
for(int i = 0; i < n-1; i++){
LL a2, m2;
cin >> a2 >> m2;
LL k1, k2;
LL d = exgcd(a1, a2, k1, k2);
// 如果(m2-m1)不是d的倍数,则无解
if((m2-m1) % d){
flag = false;
break;
}
// 扩大k1为目标解
k1 *= (m2-m1) / d;
LL t = a2/d;//k1的通解的为k1 + k*(a2/d)
k1 = (k1 % t + t) % t;// k1取最小的正整数解
// k1 = k1 + k*a2/d; k2 = k2 + k*a1/d;
// 把k1代回x = k1*a1 + m1
// 则x = k1*a1 + m1 = (k1*a1 + m1) + k*(a1*a2/d);
// 合并两个式子的时候
// 更新m1为k1*a1+m1
// 更新a1为a1和a2的最小公倍数a1*a2/d
m1 = k1 * a1 + m1;
a1 = a1/d * a2;
}
if(flag)cout << (m1 % a1 + a1) % a1 << endl;
else puts("-1");
return 0;
}