表达整数的奇怪方式:
#include <iostream>
using namespace std;
typedef long long LL;
int n;
LL exgcd(LL a, LL b, LL &x, LL &y)//扩展欧几里得求最大公约数
{
if(b == 0)
{
x = 1, y = 0;
return a;
}
long long x1,y1,gcd;
gcd = exgcd(b, a % b, x1, y1);
x = y1, y = x1 - a/b*y1;//这是扩展欧几里得算法所说的公式
return gcd;
}
int main()
{
scanf("%d", &n);
LL a1, m1;
scanf("%lld%lld", &a1, &m1);
for(int i = 1; i < n; i++)
{
LL a2, m2, k1, k2;
scanf("%lld%lld", &a2, &m2);
LL d = exgcd(a1, -a2, k1, k2);//求出k1和k2,并求出最大公约数d
if((m2 - m1) % d)//无解
{
printf("-1\n");
return 0;
}
//公式:k1*a1-k2*a2==d,而此时运算时公式为:k1*a1-k2*a2==m2-m1,所以等式两边乘到d==m2-m1
k1*=(m2-m1)/d;
LL t=a2/d;//因为此时k1==k1+k*a2/d,所以先把a2/d存进来
k1=(k1%t+t)%t;//让k1为最小正整数解
m1=a1*k1+m1;//最终公式的左边
a1=abs(a1/d*a2);//最终公式的右边
}
printf("%lld\n", (m1%a1+a1)%a1);//最后的m1只是一个普通解(不一定是最小的), 而题目要求的是最小的非负整数 x,所以(m1%a1+a1)%a1)这个操作就是求最小非负整数x
return 0;
}