设有n个式子。
然后当前进行到了这样。第一个式子表示它之前所有式子的集合,第二个是新来的式子。
那么可以转化成
我们希望求得一个x同时满足两个式子。所以可以这样转化两个式子(把x2想象成一个常数,x2倍的b2可以使x满足条件)
那么式子就变成了这样
这个式子就可以认为是
利用拓展gcd进行求解可以得到一个解,为他们的gcd。
那么的解集就可以表示为
。
然后把带回1式得
。
也就是
。
所以每一次都以当前的减去之前的答案和作为新的,当前的作为新的,之前的的lcm(简称M)作为新的
构成拓展gcd求解,也就是。
以作为模数,按上式得出新的答案(PS:简单的操作就是先把M/g,这样他乘上b或者c都是相应的lcm)
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll b[100005];
ll c[100005];
ll x,y,M,ans;
ll ex_gcd(ll a,ll b)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll r=ex_gcd(b,a%b);
ll t=x;
x=y;
y=t-a/b*x;
return r;
}
ll mul(ll a,ll b,ll mode)
{
ll s=0;
while(b)
{
if(b%2==1)
{
s+=a;
s%=mode;
}
a=(a+a)%mode;
b=b/2;
}
return s;
}
int main()
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%lld%lld",&b[i],&c[i]);
}
M=b[1],ans=c[1];
for(int i = 2;i <= n;i++)
{
ll aa=M,bb=b[i],cc=c[i]-ans;
ll gg=ex_gcd(aa,bb);
if(cc%gg)
{
printf("-1");
return 0;
}
M/=gg;M*=bb;//因为推倒得出这次的x前的系数是cc/gg*M也就是只能除下去一次gg
x=(x%M+M)%M;
ans+=mul(mul(M/bb,(cc%M+M)%M,M),x,M)%M;//这也是我多次试验之后发现的结果,这步的乘法必须为cc,M/bb的lcm乘以x,所以写过的bb/gg,cc/gg,但是M没除,也对了,因为最后也是lcm
ans=(ans%M+M)%M;
}
printf("%lld",(ans%M+M)%M);
return 0;
}//最终根据证明,取模的数是M*bb/gg。