标签:read psu c++ exgcd getchar == amp html getch
对于一个同余方程
对于第一个和第二个式子
则有:
ans=a1?+k1?∗n1?
ans=a2?+k2?∗n2?
就有:
a1?+k1?∗n1?=a2?+k2?∗n2?
k1?∗n1?−k2?∗n2?=a2?−a1?
故我们设c=a2?−a1? 再变化一下形式就有:
k1?∗n1?+(−k2?)∗n2?=c
令 gcd=gcd(n1?,n2?)
这样我们就可以通过exgcd来求出一组解x1?,y1?
满足 x1?∗n1?+y2?∗n2?=gcd
故:x1?∗d/g∗n1?+y2?∗d/g∗n2?=g∗c/gcd
则: k1?=x1?∗c/gcd,k2?=y1?∗c/gcd
从而得到一组通解((k1+q)*n1+(k2-p)*n2=c)
k1?=k1+q=k1?+n2/gcd∗T
k2?=k2-p=k2?−n1/gcd∗T
要使所求得的解最小且为正整数则可以根据 k1? 的通解形式求得
mink1?=(k1?%(n2?/gcd)+n2?/gcd)%(n2?/gcd)
再带入ans=a1?+mink1?∗n1? 得到 ans
令 A 为合并后的 a , N 为合并后的 n
所以N=lcm(n1?,n2?)=n1?∗n2?/gcd
根据ans≡A (mod N) 且 ans 是满足该式子最小的值
得到: A=ans
代码
#include<bits/stdc++.h> using namespace std; #define ll __int128 ll ans,a[100010],n[100010],N,a1,a2,n1,n2,c,gcd,x,y; long long read() { ll f=1,x=0; char ss=getchar(); while(ss<‘0‘||ss>‘9‘){if(ss==‘-‘)f=-1;ss=getchar();} while(ss>=‘0‘&&ss<=‘9‘){x=x*10+ss-‘0‘;ss=getchar();} return f*x; } void exgcd(ll aa,ll bb,ll &gcd,ll &x,ll &y) { if(!bb) { gcd=aa; x=1,y=0; return; } exgcd(bb,aa%bb,gcd,x,y); ll tr=x; x=y; y=tr-aa/bb*y; } long long zs() { a1=a[1],n1=n[1]; for(ll i=2;i<=N;i++) { a2=a[i],n2=n[i]; c=a2-a1; exgcd(n1,n2,gcd,x,y);//n1*x+n2*y=gcd(n1,n2)的解 if(c%gcd==0) { ll k1=x*c/gcd;//n1*k1+n2*k2=c的解 ll mink1=(k1%(n2/gcd)+(n2/gcd))%(n2/gcd);//k1通解:k1=k1+(n2/gcd)*t ans=mink1*n1+a1;//这2个方程的解 //合并2个方程 n1=(n1*n2)/gcd; a1=ans; } else return -1; } return ans; } int main() { N=read(); for(ll i=1;i<=N;i++) n[i]=read(),a[i]=read(); cout<<zs(); return 0; }
部分参考来自https://www.luogu.org/blog/sumijie/solution-p4777。
标签:read psu c++ exgcd getchar == amp html getch
原文地址:https://www.cnblogs.com/oierglh/p/11230965.html