青蛙的约会
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 122871 | Accepted: 26147 |
Description
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
Input
输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。
Output
输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"
Sample Input
1 2 3 4 5
Sample Output
4
Source
题目分析
首先,我们可以轻松的列出方程:
设走了t步,x,y,m,n,L含义如题。
则x+m*t≡y+n*t (mod L)
移项:(x-y)+t(m-n)≡0(mod L)
这个式子等价于(x-y)+t(m-n)=kL
//t和k才是未知数
再移项:kL-t(m-n)=(x-y)
为了化出不定方程的标准形式(不化也可以),再改成: kL+t(n-m)=(x-y)
记n-m=p,x-y=q
则kL+tp=q
//再次重申,t和k才是未知数!
上式已经是标准的不定方程了,然后怎么解它呢?
以下是重点
首先,它有解的前提是gcd(L,p)|q。(整除符号,不是或运算(QωQ))
所以我们先求gcd(L,p)。做一次拓欧,求出gcd(L,p),同时我们求出了(拓欧的)x0,y0先放着。(为了不和题目的x,y冲突)
接着,如果gcd(L,p)不整除q,那么之后无法做下去了,此题无解。
1 #include<iostream> 2 #include<string> 3 #include<cmath> 4 #include<algorithm> 5 usingnamespace std; 6 7 __int64 x,y,a,b,c,d; 8 __int64 n,m,X,Y,L; 9 10 __int64 gcd(__int64 a,__int64 b) 11 { 12 __int64 t,d; 13 if(b==0) 14 { 15 x=1; 16 y=0; 17 return a; 18 } 19 d=gcd(b,a%b); 20 t=x; 21 x=y; 22 y=t-(a/b)*y; 23 return d; 24 } 25 26 int main() 27 { 28 while(scanf("%I64d%I64d%I64d%I64d%I64d",&X,&Y,&m,&n,&L)==5) 29 { 30 a=n-m; 31 b=L; 32 c=X-Y; 33 d=gcd(a,b); 34 if(c%d!=0) 35 { 36 printf("Impossible "); 37 continue; 38 } 39 x=x*(c/d); 40 y=y*(c/d); 41 42 /*通解: 43 x1=x+b/d*t; 44 y1=y-a/d*t; 45 t为任意整数 46 */ 47 //找最小的x1,即求x+b/d*t最小,那么只有t为某一个数时才最小 48 //显然t必须与x正负相反才有最小,那么就看做x-b/d*t,这个式子的最小值便是t=x/(b/d)时,注意这是整型除法 49 __int64 k=x*d/b; 50 k=x-k*b/d; 51 if(k<0) 52 k+=b/d; 53 printf("%I64d ",k); 54 } 55 return0; 56 }
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <vector> 6 #include <string> 7 #include <queue> 8 #include <stack> 9 #include <algorithm> 10 11 #define INF 0x7fffffff 12 #define EPS 1e-12 13 #define MOD 1000000007 14 #define PI 3.141592653579798 15 #define N 100000 16 17 using namespace std; 18 19 typedef long long LL; 20 typedef double DB; 21 22 LL e_gcd(LL a,LL b,LL &x,LL &y) 23 { 24 if(b==0) 25 { 26 x=1; 27 y=0; 28 return a; 29 } 30 LL ans=e_gcd(b,a%b,x,y); 31 LL temp=x; 32 x=y; 33 y=temp-a/b*y; 34 return ans; 35 } 36 37 LL cal(LL a,LL b,LL c) 38 { 39 LL x,y; 40 LL gcd=e_gcd(a,b,x,y); 41 if(c%gcd!=0) return -1; 42 x*=c/gcd; 43 b/=gcd; 44 if(b<0) b=-b; 45 LL ans=x%b; 46 if(ans<=0) ans+=b; 47 return ans; 48 } 49 50 int main() 51 { 52 LL x,y,m,n,L; 53 while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L)!=EOF) 54 { 55 LL ans=cal(m-n,L,y-x); 56 if(ans==-1) printf("Impossible "); 57 else printf("%lld ",ans); 58 } 59 return 0; 60 }
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 long long x, y, m, n, l, k, t, d, va, vb, ba, bb; 7 long long extgcd(long long a, long long b, long long &x, long long &y) 8 { 9 long long d = a; 10 if (b != 0) 11 { 12 d = extgcd(b, a%b, y, x); 13 y = y - a / b * x; 14 } 15 else 16 { 17 x = 1; y = 0; 18 } 19 return d; 20 } 21 int main() 22 { 23 cin >> ba >> bb >> va >> vb >> l; 24 m = va - vb; n = bb - ba; 25 d = extgcd(m, l, x, y); 26 if (n%d != 0) 27 { 28 puts("Impossible"); 29 return 0; 30 } 31 t = l / d; 32 k = (x*(n / d) % t + t) % t; 33 if (k < 0) k += l; 34 cout << k << endl; 35 return 0; 36 }
ax+by=c问题
问题:ax+by=c,已知a、b、c,求解使该等式成立的一组x,y。其中a、b、c、x、y均为整数
a,b的最大公约数为gcd(a,b)。如果c不是gcd(a,b)的倍数,则该等式无解,因为等式左边除以gcd(a,b)是整数,
而等式右边除以gcd(a,b)后为小数。(根据解方程的时候,在等式的左右两边同时除以非0的整数,等式依然成立)
因此,只有当c是gcd(a,b)的倍数的时候,该等式有解。这样,可以通过计算使ax1+by1=gcd(a,b)成立的x1、y1,
然后有x=(c/gcd(a,b))*x1,y=(c/gcd(a,b))*y1,得到x,y。
1 // 等式ax+by=c,已知a、b、c,求x和y。 2 // 解该线性方程等同于解同余式ax = c(mod b) 3 // 返回值表示是否有解,true有解,false无解 4 bool linear_equation(int a, int b, int c, int &x, int &y) 5 { 6 int n = extended_euclid(a, b, x, y); 7 if(c%n) 8 return false; 9 int k = c/n; 10 x *= k; 11 y *= k; 12 return true; 13 }