解题报告
思路:
青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,假设他们跳t次相遇。
则:
==> (x+t*m)%l=(y+t*n)%l
==> (x-y)%l==((m-n)*t)%l
==> (m-n)*t==(x-y) ( mod l )------(1)
令a=(m-n),b=(x-y),n=l,t=x;则式子(1):
a*x==b(mod n)
这就是同余方程。
--------------------------华丽丽的分割线--------------------------
下面求解同余方程。
a*x==b(mod n)
表示a和b关于n同余,即(a*x)%n==b%n;
移项得((a*x)-b)%n==0;
可以理解成(a*x)-b是n的倍数;
设倍数为y,则(a*x)-(b)=n*y;
移项得:
(a*x)-(n*y)=b;
令A=a,B=n,C=b;
(A*x)-(B*y)=C;
这是“二元一次”方程
--------------------------华丽丽的分割线--------------------------
下面求解不定方程。
扩展欧几里得:
(A*x)-(B*y)=gcd(A,B);
解x'和y'(x'和y'可能为负和0)
则
==>(A*x)*( C/gcd(A,B) ) - (B*y)*( C/gcd(A,B) )=gcd(A,B)*( C/gcd(A,B) );(若C不是gcd(A,B)的倍数则无解)
解x0=x'*( C/gcd(A,B) ) ,y0=y'*( C/gcd(A,B) )
x0,y0是方程(A*x)-(B*y)=C的特解;
通解:
x=x0+t*dx;(dx=B/gcd(A,B))
y=y0-t*dy;(dy=A/gcd(A,B)) ---(t为任意整数)
很容易得到特解(x0,y0),那么通解这么求出来的?
任取一组解(x1,y1)
则:A*x1+B*y1=gcd(A,B)=A*x0+B*y0;
变形得A(x1-x0)=B(y0-y1);
两边同除d=gcd(A,B);
得A'*(x1-x0)=B'(y0-y1) A'=A/d,B'=B/d;
A'和B'互素,则x1-x0一定是B'的整数倍,设x1-x0=t*B',代入求得:
y0-y1=t*A';
同理得:
x1-x0=t*B';
--------------------------华丽丽的分割线--------------------------
回到正题上
这题只要求同余方程,只需要求出最小跳的次数t。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
void egcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if(!b)
{
d=a;x=1;y=0;
}
else
{
egcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
LL modeq(LL a,LL b,LL n)
{
LL e,d,x,y;
egcd(a,n,d,x,y);
if(b%d)return 0;
else
{
LL t=n/d;
e=x*(b/d);
e=(e%t+t)%t;
return e;
}
}
int main()
{
LL a,b,x,y,n,l,m;
while(~scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l))
{
if(n>m)
a=n-m,b=x-y;
else a=m-n,b=y-x;
LL ans=modeq(a,b,l);
if(ans==0)
printf("Impossible\n");
else printf("%lld\n",ans);
}
}
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 89894 | Accepted: 16180 |
Description
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
Input
Output
Sample Input
1 2 3 4 5
Sample Output
4
Source