扩展欧几里德问题
我們先來看這個問題
求最大公約數的gcd(m,n)方法也可以如下定義:
如果m%n為0,那么gcd(m,n)的值為n.
否則,gcd(m,n)就是gcd(n,m%n)
編寫一個遞歸的方法來求最大公約數。編寫一個測試程序,計算gcd(24,16)和gcd(255,5)
我們先引入歐幾里德的證明
歐幾里德證明
gcd(a,b)=gcd(b,a%b)
a=kb+r??? r=a%b? r=a-kb
d為gcd(a,b)那么可以推出d為gcd(b,a%b)
寫成代碼的形式:
intgcd(int m,int n) {if(!(m%n))returnn;return gcd(n,m%n);//return m%n==0?n:gcd(n,m%n);//return n?gcd(n,m%n):m; } 下面我們來看一道簡單的題目(poj1061) 青蛙的約會
| Time Limit:?1000MS | ? | Memory Limit:?10000K |
| Total Submissions:?100511 | ? | Accepted:?19307 |
Description
兩只青蛙在網上相識了,它們聊得很開心,于是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,于是它們約定各自朝西跳,直到碰面為止??墒撬鼈兂霭l之前忘記了一件很重要的事情,既沒有問清楚對方的特征,也沒有約定見面的具體位置。不過青蛙們都是很樂觀的,它們覺得只要一直朝著某個方向跳下去,總能碰到對方的。但是除非這兩只青蛙在同一時間跳到同一點上,不然是永遠都不可能碰面的。為了幫助這兩只樂觀的青蛙,你被要求寫一個程序來判斷這兩只青蛙是否能夠碰面,會在什么時候碰面。?我們把這兩只青蛙分別叫做青蛙A和青蛙B,并且規定緯度線上東經0度處為原點,由東往西為正方向,單位長度1米,這樣我們就得到了一條首尾相接的數軸。設青蛙A的出發點坐標是x,青蛙B的出發點坐標是y。青蛙A一次能跳m米,青蛙B一次能跳n米,兩只青蛙跳一次所花費的時間相同。緯度線總長L米?,F在要你求出它們跳了幾次以后才會碰面。?
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 5Sample Output
4分析題意之后不難得出
a*x+ b*y=gcd
那么我們引入擴展歐幾里德的概念
1.擴展歐幾里德解的前提
現在我們知道了a 和b 的最大公約數是gcd,那么,我們一定能夠找到這樣的 x和 y,使得:a*x + b*y = gcd
我們就可以用x0 和y0 表示出整個不定方程的通解:
x= x0 + (b/gcd)*t
y = y0 – (a/gcd)*t
2.擴展歐幾里德解的思路:
a*x + b*y= gcd
a*1 + b*0= gcd
3.擴展歐幾里德解的證明:
1.a*x+ b*y=gcd
2.b*x1+ (a%b)*y1=gcd
3.a%b= a - (a/b)*b
由此可以得出:
gcd= b*x1 + (a-(a/b)*b)*y1?=b*x1+ a*y1 – (a/b)*b*y1?=a*y1+ b*(x1 – a/b*y1)
寫成代碼的形式:
long long ex_gcd(long long a,long long b,long long &x,long long &y) {if(b == 0){x = 1;y = 0;return a;}long long r = ex_gcd(b,a%b,x,y);long long temp = x;x = y;y = temp - a/b*y;return r; }
完整源代碼:
#include <iostream> #include <stdio.h> using namespace std; long long ex_gcd(long long a,long long b,long long &x,long long &y) {if(b == 0){x = 1;y = 0;return a;}long long r = ex_gcd(b,a%b,x,y);long long temp = x;x = y;y = temp - a/b*y;return r; } int main() {long long x,y,m,n,l,p,q;scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);int r = ex_gcd(n-m,l,p,q);if((x-y)%r)cout<<"Impossible";else{long long d = l/r,dd = (x-y)/r;p *= dd;p = (p%d+d)%d;printf("%lld\n",p);}return 0; }
附上完整課件資料:http://download.csdn.net/detail/k183000860/9334973
轉載于:https://www.cnblogs.com/yefengCrazy/p/5636641.html
總結
- 上一篇: caja 原理 : 前端
- 下一篇: quick 中实现单例