poj 1061 (扩展欧几里德算法)


首先先抛出一个例题:


                                                                                                    青蛙的约会
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 89761   Accepted: 16131

Description

两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙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


涉及知识点:ext_gcd

代码如下:

#include<stdio.h>
#include<math.h>
#define LL long long

LL extend_gcd(LL a, LL b, LL &x, LL &y)
{
    if(b==0)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL d = extend_gcd(b, a%b, x, y);
    LL t = x;
    x = y;
    y = t-a/b*y;
    return d;
}

int main()
{
    LL x, y, n, m, L;
    LL a,b,c,d;

    while(~scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &L))
    {
        LL p,q;
        a=n-m, b=L, c = x-y;
        d = extend_gcd(a, b, p, q);

        if(c%d!=0) printf("Impossible
");
        else
        {
            p = p*(c/d);
            p = (p%b + b)%b;
            printf("%lld
", p);
        }
    }
    return 0;

注意:

ext_gcd模板求得的只是 当 ax + by = gcd(a,b)时,x 和 y 的值。 但是当ax ' + b y' = c 如果有解,则应满足以下情况:,c能够整除gcd(a, b),也就是c = k  *(gcd(a, b)) 其中k为整数。那么此时的 x' 就等于kx, y' 就等于 ky,即 x' = kx,    y = ky',对应文中代码部分为: p = p*(c/d);。如果想求最小正整数解的话,就要加上 p = (p%b + b)%b 了。

—————————————————————————————————————————————————————————————————————————————

          今天看了一下gcd算法,本来学的教材上有这个,但不知道还叫欧几里德算法,于是又重新看了一边,搜的时候没想到还有新的收获,又看到了拓展欧几里德算法。

  先说一下gcd吧,也叫辗转相除法。给定两个数 a,b , 求两个数中的最大公约数。

 int gcd(int n, int m) // n>m
{
  if(n%m == 0)
         return m;
 else
        return (m, n%m);

}

思路比较简单,两个数(a, b,其中a>b)的最大公约数就等于其中较小数(b)和(a%b)这两个数的最大公约数。

最小公倍数等于 两个数的乘积除以两个数的最大公约数。

—————————————————————————————————————————————————————————————————————————————

再说一下extend_gcd( 拓展欧几里得算法),ext_gcd 算法由裴蜀定理中得出:

          知识点:  在数论中,裴蜀等式裴蜀定理是一个关于最大公约数(或最大公约式)的定理。裴蜀定理得名于法国数学家艾蒂安·裴蜀,说明了对任何整数ab和它们的最大公约数d,关于未知数xy线性丢番图方程(称为裴蜀等式):

ax+by=m

有整数解时当且仅当md倍数。裴蜀等式有解时必然有无穷多个整数解,每组解xy都称为裴蜀数,可用扩展欧几里得算法求得。

例如,12和42的最大公约数是6,则方程12x+42y=6有解。事实上有(-3)×12 + 1×42 = 6及4×12 + (-1)×42 = 6。

特别来说,方程 ax+by=1 有整数解当且仅当整数ab互素

裴蜀等式也可以用来给最大公约数定义:d其实就是最小的可以写成ax+by形式的正整数。这个定义的本质是整环中“理想”的概念。因此对于多项式整环也有相应的裴蜀定理。

 

            历史历史上首先证明关于整数的裴蜀定理的并不是裴蜀,而是17世纪初的法国数学家克劳德-加斯帕·巴歇·德·梅齐里亚克Claude-Gaspard Bachet de Méziriac)。他在于1624年发表的著作《有关整数的令人快乐与惬意的问题集》(Problèmes plaisans et délectables qui se font par les nombres)第二版中给出了问题的描述和证明[1]

然而,裴蜀推广了梅齐里亚克的结论,特别是探讨了多项式中的裴蜀等式,并给出了相应的定理和证明[2]


        证明过程如下:

     整数中的裴蜀定理

         对任意两个整数ab,设d是它们的最大公约数。那么关于未知数xy线性丢番图方程(称为裴蜀等式):

      displaystyle ax+by=m

有整数解(x,y) 当且仅当md倍数。裴蜀等式有解时必然有无穷多个解。

证明

如果 ab 中有一个是0,比如a=0,那么它们两个的最大公约数是b。这时裴蜀等式变成displaystyle by=m,它有整数解(x,y) 当且仅当md 的倍数,而且有解时必然有无穷多个解,因为x 可以是任何整数。定理成立。

以下设 ab 都不为0。

A = {xa+yb; (x;y) in ^2},下面证明A中的最小正元素是ab 的最大公约数。

首先,A cap N^* 不是空集(至少包含|a||b|),因此由于自然数集合是良序的,A 中存在最小正元素d_0 = x_0a + y_0b。考虑A中任意一个正元素p=x_1a + y_1b)对d_0带余除法:设p=qd_0+r,其中q 为正整数,0 le r < d_0。但是

r = p-qd_0 =x_1a + y_1b - q ( x_0a + y_0b) in A

因此 r=0d_0  |  p。也就是说,A中任意一个正元素p都是d_0 的倍数,特别地:d_0  |  ad_0  |  b。因此d_0ab公约数

另一方面,对 ab 的任意正公约数d,设a=kdb=ld,那么

d_0 =x_0a + y_0b = ( x_0k + y_0l )d

因此 d  |  d_0。所以d_0ab最大公约数

在方程ax+by=m中,如果 m= m_0 d_0,那么方程显然有无穷多个解:

left{left( m_0 left(x_0+frac{kb}{d}
ight), m_0 left( y_0-frac{ka}{d}
ight) 
ight) mid k in mathbb{Z} 
ight}

相反的,如果ax+by=m有整数解,那么|m| in A,于是由前可知d_0  |  |m|(即d_0  |  m)。

m=1时,方程有解当且仅当ab互质。方程有解时,解的集合是

 left{left( frac{m}{d} left(x_0+frac{kb}{d}
ight), frac{m}{d} left( y_0-frac{ka}{d}
ight) 
ight) mid k in mathbb{Z} 
ight} 。其中(x_0,y_0)是方程ax+by=d的一个解,可由辗转相除法得到。

所有解中,有且仅有一个解(x,y) 满足-b le x le b-a le y le a


拓展欧几里德算法:见链接  http://zh.wikipedia.org/wiki/%E6%89%A9%E5%B1%95%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E7%AE%97%E6%B3%95

每天训练发现我比别人做的好慢,但是理解的更深刻,如果一开始学一个新知识点就搜模板,那么这样的人是走不远的,毕业之后带走的只有思维,什么荣誉,奖杯都已经不重要了。
原文地址:https://www.cnblogs.com/6bing/p/3931241.html