POJ2891 Strange Way to Express Integers

原题面:https://vjudge.net/problem/POJ-2891

题目大意:给定2n个正整数a1,a2,...,an和r1,r2,...rn,求一个最小的正整数x,满足对任意i<-[1,n]都有x=ai(mod ri),或者给出无解。

输入描述:多组输入,第一行一个整数n,代表元素的个数。接下来n行,每行两个正整数ai,ri,代表第i个二元组。

输出描述:输出满足题目条件的最小的正整数x,如果无解,输出-1。

样例输入:

2
8 7
11 9

 

样例输出:

31

 

分析:现在还只会求二元线性同余方程的通解,这个还不会求。现在还只会套个板子求一求,下次补上不套板子的。百度找了一个比较简洁的板子,按照算法进阶上写出来的我没过样例,还是太菜了啊。下次补上自己敲出来的,先用这个板子写一写。

代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e5+7;
typedef long long ll;
ll a[maxn],r[maxn];
ll exgcd(ll a,ll b,ll& x,ll& y) {
    if (!b) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = exgcd(b, a % b, x, y);
    ll z = x;
    x = y;
    y = z - y * (a / b);
    return d;
}
ll gcd(ll a,ll b) {
    return !b ? a : gcd(b, a % b);
}
ll China(int len,ll *a,ll *r) {
    ll M = a[0], R = r[0], x, y;
    for (int i = 1; i < len; i++) {
        ll 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() {
    int n;
    while (scanf("%d", &n) != EOF) {
        for (int i = 0; i < n; i++)
            scanf("%lld%lld", &a[i], &r[i]);
        ll x = China(n, a, r);
        printf("%lld\n", x);
    }
    return 0;
}
posted @ 2019-12-28 09:24  SwiftAC  阅读(170)  评论(0编辑  收藏  举报