链接: https://www.nowcoder.net/acm/contest/75/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

uu遇到了一个小问题,可是他不想答。你能替他解决这个问题吗?
问题:给你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;
}