POJ 2891 Strange Way to Express Integers

Strange Way to Express Integers

Time Limit: 1000MS Memory Limit: 131072K

Description

Elina is reading a book written by Rujia Liu, which introduces a strange way to express non-negative integers. The way is described as following:
Choose k different positive integers a1, a2, …, ak. For some non-negative m, divide it by every ai (1 ≤ i ≤ k) to find the remainder ri. If a1, a2, …, ak are properly chosen, m can be determined, then the pairs (ai, ri) can be used to express m.

“It is easy to calculate the pairs from m, ” said Elina. “But how can I find m from the pairs?”

Since Elina is new to programming, this problem is too difficult for her. Can you help her?

Input

The input contains multiple test cases. Each test cases consists of some lines.

Line 1: Contains the integer k.
Lines 2 ~ k + 1: Each contains a pair of integers ai, ri (1 ≤ i ≤ k).

Output

Output the non-negative integer m on a separate line for each test case. If there are multiple possible values, output the smallest one. If there are no possible values, output -1.

Sample Input

2
8 7
11 9

Sample Output

31

Hint

All integers in the input and the output are non-negative and can be represented by 64-bit integral types.

题意:

求是否有一个数字,可以满足从1 ~ n, x % m[i] = a[i], 不满足输出-1。

思路:

由于题目没有说明这些情况是互质的,所以就要用到扩展中国剩余定理了,也就是说要逐个判断了,举个例子:由于x是一样的,所以就有了
x % m[0] = a[0]; \rightarrow x + k0 * m[0] = a[0]; \rightarrow x = a[0] - k0 * m[0]
x % m[1] = a[1]; \rightarrow x + k1 * m[1] = a[1]; \rightarrow x = a[1] - k1 * m[1]
\rightarrow a[0] - k0 * m[0] = a[1] - k1 * m[1] \rightarrow k1 * m[1] - k0 * m[0] = a[1] - a[0];
这个时候就可以看成扩展欧几里得算法了,,形如ax + by = c;然后就是看看c % gcd是否整除判断是否是能够出现x。所以得话不断得求出x然后相加取模最后就是答案了。

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 1010;
ll Exgcd(ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll g = Exgcd(b, a % b, x, y);
    ll tmp = x;
    x = y;
    y = tmp - a / b * y;
    return g;
}
int main() {
    ll n;
    ll m[maxn], a[maxn];
    while (scanf("%lld", &n) != EOF) {
        ll lcm = 1;
        for (int i = 0; i < n; i++) scanf("%lld %lld", &m[i], &a[i]);
        bool flag = false;
        ll res = 0, x, y, aa = a[0], mm = m[0];
        for (int i = 1; i < n; i++) {
            ll gcd = Exgcd(mm, m[i], x, y);
            ll a_minu = a[i] - aa;
            if (a_minu % gcd != 0) {
                flag = true;
                break;
            }
            x *= a_minu / gcd;
            m[i] /= gcd;
            x = (x % m[i] + m[i]) % m[i];
            aa += mm * x;
            mm = mm * m[i];
            aa = (aa % mm + mm) % mm;
        }
        if (flag == false) printf("%lld\n", aa);
        else printf("-1\n");
    }
    return 0;
}

全部评论

相关推荐

昨天 22:28
门头沟学院 Java
投递科大讯飞等公司6个岗位
点赞 评论 收藏
分享
牛至超人:把哈工大,再加大加粗,看见闪闪发光的哈工大字样,面试官直接流口水
投递字节跳动等公司6个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务