UESTC 288 青蛙的约会 扩展GCD
设两只青蛙跳了t步,则此时A的坐标:x+mt,B的坐标:y+nt。要使的他们在同一点,则要满足: x+mt - (y+nt) = kL (p是整数)
化成: (n-m)t + kL = x-y (L > 0) 则变成求解同余方程: (n-m)t ≡ (x-y) mod L ,用扩展gcd解决。 且此时当 (x-y) % gcd(n-m,L) == 0 时才有解。
解同余方程ax+by = m时,假设我们已经求出了一对x0,y0,则 x0 = x*m/gcd(a,b) ,此时x0可能不是正整数,更不一定是最小正整数解,所以还需进一步处理。
令g = gcd(a,b), 对 a*x0 + b*y0 = d , 有 (a/g)*x0 +(b/g)*y0 = d/g 再变形:(a/g)(x0 + k*(b/g)) + (b/g)(y0 - k*(a/g)) = d/g 仍然成立,根据k的值可以找出所有的解,所以,x = x0+k(b/g) , 令b/g = t, 则 x = x0 + kt, 所以可以通过 x = (x0%t + t)%t 求得最小正整数解x。
Tips:为了避免gcd(n-m,L)变成负数,首先判断一下n-m的正负性,如果为负,则n-m取反成m-n,此时x-y取反成y-x,仍可求得正确结果。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define Mod 1000000007 #define SMod 10007 #define lll __int64 #define ll long long using namespace std; #define N 1000007 ll exgcd(ll a,ll b,ll &x,ll &y) { if(!b) { x = (ll)1,y = (ll)0; return a; } ll r = exgcd(b,a%b,x,y); ll t = x; x = y; y = t - a/b*y; return r; } ll gcd(ll a,ll b) { if(!b) return a; return gcd(b,a%b); } int main() { ll x,y,m,n,L; ll kx,ky; //freopen("1.txt","r",stdin); //freopen("2.txt","w",stdout); while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L)!=EOF) { ll nm = n-m; ll delta = x-y; if(nm < 0) { nm = m-n; delta = y-x; } ll d = exgcd(nm,L,kx,ky); if(delta%d) { puts("Impossible"); continue; } ll t = L/d; //printf("%lld\n",t); ll res = (((delta/d)*kx)%t + t)%t; printf("%lld\n",res); } return 0; }
作者:whatbeg
出处1:http://whatbeg.com/
出处2:http://www.cnblogs.com/whatbeg/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
更多精彩文章抢先看?详见我的独立博客: whatbeg.com