【题目描述】:
Elina正在读刘汝佳写的一本书,它介绍了一种表达非负整数的奇怪方法。方式如下:
选择k个不同的正整数a1,a2,…,ak。对于一些非负整数m,将它除以每个ai (1<=i<=k)可以得到余数ri。如果a1,a2,…,ak被适当地选择,m被确定,那么这些(ai,ri)对可以用来表示m。
Elina说:“通过m计算ri很容易。”“但是我怎么才能从这些(ai,ri)对中找到m呢?“
由于Elina对编程很陌生,这个问题对她来说太难了。你能帮助她吗?
【输入描述】:
第一行:一个整数k
以下k行:每行两个整数,表示ai和ri(1<=i<=k)。
【输出描述】:
输出一行,表示最小的非负整数m,如果没有解,输出-1。
【样例输入】:
2
8 7
11 9
【样例输出】:
31
【时间限制、数据范围及描述】:
时间:1s 空间:128M
2<=k<=10000;
注意:输入和输出中的所有整数都是非负的,可以用64位整型来表示。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a[100005],r[100005];
int n;
ll exgcd(ll a,ll b,ll &x,ll &y) {
if(b==0) return x=1,y=0,a;
ll tmp=exgcd(b,a%b,y,x);
y-=a/b*x;
return tmp;
}
ll solve() {
ll M=a[1],R=r[1],x,y,d;
for(int i=2; i<=n; i++) {
d=exgcd(M,a[i],x,y);
if((R-r[i])%d!=0) return -1;
x=(R-r[i])/d*x%a[i];
R-=x*M;
M=M/d*a[i];
R%=M;
}
return (R%M+M)%M;
}
int main() {
while(~scanf("%d",&n)) {
for(int i=1; i<=n; i++)scanf("%lld%lld",&a[i],&r[i]);
printf("%lld\n",solve());
}
return 0;
}