zoukankan      html  css  js  c++  java
  • POJ 1061 青蛙的约会(扩展欧几里得)

    题目大意:

      就是说,给你两个起始的x和y,然后x每次增加m,y每次增加n,以及长度L,求出最小的变化次数T,有(x+m*T)-(y+n*T)==P*L.

    解题思路:

      裸裸的扩展欧几里得。

      分析:假设跳了T次以后,青蛙1的坐标便是x+m*T,青蛙2的坐标为y+n*T。它们能够相遇的情况为(x+m*T)-(y+n*T)==P*L,其中P为某一个整数,变形一下

    得到(n-m)*T+P*L==x-y   我们设a=(n-m),b=L,c=x-y,T=x,P=y.于是便得到ax+by==c。激动啊,这不就是上面一样的式子吗。

    直接套用扩展欧几里得函数,得到一组解x,y。由于问题是问最少跳多少次,于是只有x是我们需要的信息。那么再想,x是最小的吗?

      答案是可能不是!那么如何得到最小解呢?  我们考虑x的所有解的式子: x=x0+b/d*t。x0是我们刚刚求到的,很显然右边是有个单调函数,当t为某一个与x正负性质相反的数时,可以得到最小的x。 令x的正负性质为正,那么x=x0-b/d*t1 (t1==-t)。令x==0,那么t=x0*d/b,最小的x等于x0减去t*b/d。这里得到的x可能是负数,如果是负数,我们再为它加上一个b/d即是所求答案了!

    代码:

     1 # include<cstdio>
     2 # include<iostream>
     3 # include<fstream>
     4 # include<algorithm>
     5 # include<functional>
     6 # include<cstring>
     7 # include<string>
     8 # include<cstdlib>
     9 # include<iomanip>
    10 # include<numeric>
    11 # include<cctype>
    12 # include<cmath>
    13 # include<ctime>
    14 # include<queue>
    15 # include<stack>
    16 # include<list>
    17 # include<set>
    18 # include<map>
    19 
    20 using namespace std;
    21 
    22 const double PI=4.0*atan(1.0);
    23 
    24 typedef long long LL;
    25 typedef unsigned long long ULL;
    26 
    27 # define inf 999999999
    28 
    29 LL x,y,a,b,c,d;
    30 LL n,m,X,Y,L;
    31 
    32 LL ext_gcd( LL a,LL b )
    33 {
    34     LL t,d;
    35     if ( b==0 )
    36     {
    37         x = 1;
    38         y = 0;
    39         return a;
    40     }
    41     d = ext_gcd(b,a%b);
    42     t = x;
    43     x = y;
    44     y = t-(a/b)*y;
    45     return d;
    46 }
    47 
    48 
    49 int main(void)
    50 {
    51     while (cin>>X>>Y>>m>>n>>L )
    52     {
    53         a = n-m;
    54         b = L;
    55         c = X-Y;
    56         d = ext_gcd(a,b);
    57         if ( c%d!=0 )
    58         {
    59             printf("Impossible
    ");
    60             continue;
    61 
    62         }
    63         x = x*(c/d);
    64         y = y*(c/d);
    65 
    66         LL k = x*d/b;
    67         k = x-k*b/d;
    68         if ( k<0 )
    69         {
    70             k+=b/d;
    71         }
    72         cout<<k<<endl;
    73     }
    74 
    75 
    76     return 0;
    77 }
  • 相关阅读:
    浅拷贝与深拷贝的实现
    Java批量下载生成zip文件
    jsp页面内容导出到Excel中
    Table动态增加删除行
    JavaScript校验日期格式
    java实现算术表达式求值
    XCode 4 编译错误大全整理
    VMWare安装黑苹果Mac OS
    ODA(Open Design Alliance)介绍
    AutoCAD 2010 开发与之前版本的区别
  • 原文地址:https://www.cnblogs.com/wikioibai/p/4455669.html
Copyright © 2011-2022 走看看