【Luogu】P1516青蛙的约会(线性同余方程,扩展欧几里得)
定理:对于方程\(ax+by=c\),等价于\(a*x=c(mod b)\),有整数解的充分必要条件是c是gcd(a,b)的整数倍。
——信息学奥赛之数学一本通
避免侵权。哈哈。
两只青蛙跳到一格才行,所以说
\(x+mt=y+nt(mod l) \)
\((x-y)+(m-n)t=0(mod l)\)
\((m-n)t+ls=(y-x) s属于整数集\)
令a=n-m,b=l,c=gcd(a,b),d=x-y
则有\( at+bs=d\)
扩展欧几里得求解。
设c=gcd(a,b),若d/c 不是整数则无解。
最小解=(c*(d/c)%b+b)%b
这里是扩展欧几里得的代码。
long long exgcd(long long a,long long b,long long &x,long long &y){ if(b==0){ y=0;x=1; return a; } long long ret=exgcd(b,a%b,x,y); long long tmp=x;x=y;y=tmp-a/b*y; return ret; }
附上解题代码
#include<iostream> #include<cstdio> using namespace std; long long p,q; long long exgcd(long long a,long long b,long long &x,long long &y){ if(b==0){ y=0;x=1; return a; } long long ret=exgcd(b,a%b,x,y); long long tmp=x;x=y;y=tmp-a/b*y; return ret; } int main(){ long long n,m,x,y,l; cin>>x>>y>>m>>n>>l; long long a=x-y,b=n-m; if(b<0){ b=-b;a=-a; } long long c; if((a)%(c=exgcd(b,l,p,q))){ printf("Impossible"); return 0; } printf("%lld",((a)/c*p%(l/c)+(l/c))%(l/c)); return 0; }