题目链接:
http://poj.org/problem?id=1061
题目意思:
两只青蛙,开始的位置分别为x和y,在长度为L的循环直线上,分别以速度m和n从开始位置跳,跳一次两只青蛙的时间相同。
问跳多少次两只青蛙能到达同一点,如果不能输出Impossible.
解题思路:
有(x+ma)%L=(y+na)%L
得(m-n)a=(y-x)%L
实际上就是求出最小的正整数a使得上式满足,很裸的扩展欧几里得算法的应用。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF (1<<30)
#define PI acos(-1.0)
#define ll __int64
using namespace std;
/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/
struct Frog
{
ll p,s;
};
void swap(struct Frog &a,struct Frog &b)
{
struct Frog t;
t=a;
a=b;
b=t;
return ;
}
ll egcd(ll a,ll b,ll & x,ll & y)
{
if(b==0)
{
x=1,y=0;
return a;
}
ll d=egcd(b,a%b,x,y);
ll t=x;
x=y,y=t-a/b*y;
return d;
}
bool lineq(ll a,ll b,ll c,ll & x,ll &y,ll & t)
{
t=egcd(a,b,x,y);
// printf(":%I64d\n",t);
if(c%t)
return false;
x=x*c/t;
y=y*c/t;
return true;
}
int main()
{
Frog a,b;
ll l;
while(scanf("%I64d%I64d",&a.p,&b.p)!=EOF)
{
scanf("%I64d%I64d%I64d",&a.s,&b.s,&l);
if(a.s<b.s) //交换下,这样避免求对大公约数的时候出问题
swap(a,b);
ll c=b.p-a.p;
ll x,y,d;
bool ans=lineq(a.s-b.s,l,c,x,y,d);
if(ans==false)
printf("Impossible\n");
else
{
if(x<0) //找到最小的正整数x
{
while(x<0)
x+=l/d;
}
else
{
while(x>=0)
x-=l/d;
x+=l/d;
}
printf("%I64d\n",x);
}
}
return 0;
}