`
王宝林
  • 浏览: 15017 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

欧几里得算法、拓展欧几里得算法解青蛙约会问题

阅读更多

青蛙约会问题:

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

采用欧几里得算法和拓展欧几里得算法解决该问题,算法步骤如下:

1.问题可描述为:(m-n)*t+p*L=y-x,令a=m-n,b=y-x.

a*t+p*L=b

2.于是化为解决求a * x + b * y = n的整数解的问题。

 

  • 先计算Gcd(a,b),若n不能被Gcd(a,b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a,b),得到新的不定方程a' * x + b' * y = n',此时Gcd(a',b')=1;
  • 利用上面所说的欧几里德算法求出方程a' * x + b' * y = 1的一组整数解x0,y0,则n' * x0,n' * y0是方程a' * x + b' * y = n'的一组整数解;
  • 根据数论中的相关定理,可得方程a' * x + b' * y = n'的所有整数解为:

x = n' * x0 + b' * t

 

y = n' * y0 - a' * t(t为整数)

 

  • 上面的解也就是a * x + b * y = n 的全部整数解。

以下为欧几里得算法和拓展欧几里得算法的原理,引自木瓜的博客

欧几里得算法:

 

欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理:

定理:gcd(a,b) = gcd(b,a mod b)

证明:a可以表示成a = kb + r,则r = a mod b

假设d是a,b的一个公约数,则有d|a, d|b,而r = a - kb,因此d|r,因此d是(b,a mod b)的公约数;

假设d 是(b,a mod b)的公约数,则d | b , d |r ,但是a = kb +r,因此d也是(a,b)的公约数;

因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证

欧几里德算法就是根据这个原理来做的,其算法用C++语言描述为: 

 

int Gcd(int a, int b)
{
     if(b == 0)
          return a;
       return Gcd(b, a % b);
}

 

当然你也可以写成迭代形式:

 

int Gcd(int a, int b)
{
      while(b != 0)
      {
          int r = b;
      b = a % b;
        a = r;
      }
      return a;
}

拓展欧几里得算法

扩展欧几里德算法是用来在已知a, b求解一组x,y使得a*x+b*y=Gcd(a,b)(解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及方程组中。下面是一个使用C++的实现:

int exGcd(int a, int b, int &x, int &y)
{
     if(b == 0)
     {
          x = 1;
          y = 0;
          return a;
     }
     int r = exGcd(b, a % b, x, y);
     int t = x;
     x = y;
     y = t - a / b * y;
   return r;
}
 
分享到:
评论

相关推荐

    poj 1061 青蛙的约会

    ### poj 1061 青蛙的约会 #### 题目背景与问题描述 本题目属于经典的数学问题之一...本题主要考察了数学中的最大公约数和最小公倍数概念及其应用,特别是扩展欧几里得算法的应用,这对于理解问题和解决问题至关重要。

    自己喜欢的poj入门题目

    接下来,`_int64 exGcd(__int64 a, __int64 b)` 是扩展欧几里得算法的实现,用于求解形如 ax + by = gcd(a, b) 的整数解。当 b 为 0 时,返回 a 作为结果,并初始化 x 和 y 分别为 1 和 0。否则,递归调用 exGcd ...

    数论7-17题解1

    扩展欧几里得算法不仅能够找到最大公约数,还能同时求出贝祖等式(Bézout's identity)的解,即存在整数x和y使得`ax + by = gcd(a, b)`。 在C题 "Strange Way to Express Integers" 中,面对的是一组非互质模数的...

    Python算法与设计模式面试题汇总!.docx

    - 解决这类问题通常需要利用模运算和扩展欧几里得算法求解最大公约数。 23. **链表节点两两交换**: - 通过迭代或递归,每次交换相邻节点,最后返回新的链表头。 24. **寻找数组中和为目标值的两个索引**: - ...

    POJ题目分类-题库分类

    需要了解基本的数论概念和定理,如欧几里得算法、模运算等。 8. **贪心**:贪心策略是每次选择局部最优解以期望得到全局最优解,例如Packets、Communication System、Gone Fishing等。这类问题需要分析问题特性,找...

    C、C++编程题目和代码1.pdf

    - 知识点:欧几里得算法,递归或循环实现。 9. **打印圣诞树(用“#”)** - 知识点:字符串操作,嵌套循环,控制输出格式。 10. **n的阶乘和(输入一个n,求n以内的阶乘之和)** - 知识点:阶乘计算,循环,...

    初学者练题开始------在POJ上(注:是百练)

    这些题目覆盖了算法基础、数学应用、数据结构、逻辑推理等多个方面,通过解决这些题目,初学者可以逐步建立编程思维,提升问题解决能力。在POJ上进行实践,不仅可以检验代码正确性,还可以看到自己的解法与其他...

    求多边形面积、周长、重心

    对于这样的情况,可能需要使用更复杂的算法,如扫描线算法或者格雷代码遍历等。但以上代码足以处理简单的多边形计算需求。 总结,本篇文章介绍了如何使用C#编程语言来计算多边形的面积、周长和重心,这是图形学和...

Global site tag (gtag.js) - Google Analytics