poj-1061-扩展欧几里得算法-青蛙的约会

题目链接:

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;
}



你可能感兴趣的:(poj-1061-扩展欧几里得算法-青蛙的约会)