链接: https://www.nowcoder.net/acm/contest/75/B
来源:牛客网
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
uu遇到了一个小问题,可是他不想答。你能替他解决这个问题吗?
问题:给你k对a和r是否存在一个正整数x使每队a和r都满足:x mod a=r,求最小正解x或无解。
问题:给你k对a和r是否存在一个正整数x使每队a和r都满足:x mod a=r,求最小正解x或无解。
输入描述:
第一行是正整数k(k<=100000) 接下来k行,每行有俩个正整数a,r(100000>a>r>=0)
输出描述:
在每个测试用例输出非负整数m,占一行。 如果有多个可能的值,输出最小的值。 如果没有可能的值,则输出-1。
一个传统的线性同余方程组~~偶尔间看到了大佬的题解~记录下来观赏一番;
#include <cstdio>
#include<iostream>
using namespace std;
#define LL long long
const LL maxn = 20;
//拓展欧几里得定理,求ax+by=gcd(a,b)的一组解(x,y),d=gcd(a,b)
void exGcd(LL a, LL b, LL &d, LL &x, LL &y)
{
if (b == 0)
{
d = a;
x = 1;
y = 0;
}
else
{
exGcd(b, a%b, d, y, x);
y = y- x*(a / b);
}
}
LL Chinese_Remainder(LL n, LL a[], LL b[])
{
LL m1, r1, m2, r2, flag = 0, i, d, x, y, c, t;
m1 = a[0], r1 = b[0];
flag = 0;
for (i = 1; i<n; i++)
{
m2 = a[i], r2 = b[i];
if (flag)continue;
exGcd(m1, m2, d, x, y);//d=exGcd(m1,m2);x*m1+y*m2=d;
c = r2 - r1;
if (c%d)//对于方程m1*x+m2*y=c,如果c不是d的倍数就无整数解
{
flag = 1;
break;
}
t = m2 / d;//对于方程m1x+m2y=c=r2-r1,若(x0,y0)是一组整数解,那么(x0+k*m2/d,y0-k*m1/d)也是一组整数解(k为任意整数)
//其中x0=x*c/d,y0=x*c/d;
x = (c / d*x%t + t) % t;//保证x0是正数,因为x+k*t是解,(x%t+t)%t也必定是正数解(必定存在某个k使得(x%t+t)%t=x+k*t)
r1 = m1*x + r1;//新求的r1就是前i组的解,Mi=m1*x+M(i-1)=r2-m2*y(m1为前i个m的最小公倍数);对m2取余时,余数为r2;
//对以前的m取余时,Mi%m=m1*x%m+M(i-1)%m=M(i-1)%m=r
m1 = m1*m2 / d;
}
if (flag)
return -1;
if (n == 1 && r1 == 0)
return m1;//结果不能为0
return r1;
}
int main()
{
LL T, i, n, tt = 0;
LL a[maxn], b[maxn];
cin >> n;
if (n > 20)
{
cout << -1 << endl;
return 0;
}
for (i = 0; i < n; i++)
cin >> a[i] >> b[i];
cout << Chinese_Remainder(n, a, b) << endl;
return 0;
}