UOJ—21表达整数的奇怪方法

【题目描述】:

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;
}

猜你喜欢

转载自blog.csdn.net/to_more_excellent/article/details/80987822
今日推荐