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 <iostream>

#include <cstdio>

#include <stdlib.h>

#include <algorithm>
#include <cstring>
using namespace std;
long long  a[100055],r[100052],n;
long long extgcd(long long  a,long long  b,long long  &x,long long  &y) 

    if(b==0) 
    { 
        x=1; 
        y=0; 
        return a; 
    } 
    long long  d=extgcd(b,a%b,x,y); 
    long long  t=x; 
    x=y; 
    y=t-a/b*y; 
    return d; 
 } 
long long  solve() { 
    long long  d, c ,i, x, y, t; 
    for(i=1;i<n;i++) { 
        c = r[i] - r[i - 1]; 
        d = extgcd(a[i - 1], a[i], x, y); 
        if(c % d != 0) return -1; 
        t = a[i] / d; 
        x = (x * (c / d) % t + t) % t; 
        r[i] = a[i - 1] * x + r[i - 1]; 
        a[i] = a[i - 1] * (a[i] / d); 
    } 
    return r[n - 1]; 

int  main(){
cin>>n;
for(long long  i=0;i<n;i++)
{
scanf("%lld%lld",&a[i],&r[i]);

}
printf("%lld\n",solve());
}

猜你喜欢

转载自blog.csdn.net/wzx1078132012/article/details/80987874