歐幾里得及其擴展

歐幾里得:ios

大意:web

設gcd(a,b) 表示 a,b的最大公約數,通常程序裏也用同名函數來計算最大公約數計算原理以下:(b不爲0時 且a和b不相等的狀況下)咱們設gcd(a,b)=d, 再設a除以b的餘數爲r1 而且必有r1<b,那麼必然有非負整數x0使得a=b*x0+r1等式成立 ,可變爲r1=a-b*x0  ,那麼r1必然也是d的倍數 這樣就有a b r1的最大公約數爲d,就是說, d=gcd(a,b)=gcd(b,r1)  其中 b>r1,如此咱們再設b除以r1的餘數爲r2 ,而且必有r2<r1,那麼必然有非負整數x1使得b=r1*x1+r2等式成立 可變爲r2=b-r1*x1  , 那麼r2必然也是d的倍數, 這樣就有a b r1 r2的最大公約數爲d  ,就是說 d=gcd(a,b)=gcd(b,r1)=gcd(r1,r2) 其中 b>r1>r2,這樣反覆咱們就會得出 d=gcd(a,b)=gcd(b,r1)=gcd(r1,r2)=……=gcd(rn-1,rn) ,其中 b>r1>r2>……>rn-1>rn=d,那麼必然有非負整數xn-1使得rn-2=(rn-1*xn-1) +rn等式成立 可變爲rn=rn-2 -(rn-1*xn-1),而後咱們發現rn-1除以rn其他數就爲0 這就能夠判斷rn爲最大公約數d,這就是歐幾里德算法求最大公約數的算法了(上述算法當a=b的時候咱們可知最大公約數就爲其自己一樣適用  同時咱們規定當b=0的時候gcd(a,b)=a)。咱們經過程序來求解就有:
int Gcd(int a, int b)
{
if(b == 0) return a;
return Gcd(b, a % b);
} 遞歸形式
算法

例題:函數

 

求兩個正整數的最大公約數。spa


Input
輸入數據含有很少於50對的數據,每對數據由兩個正整數(0 < n1,n2 < 232)組成。
code

Output
對於每組數據n1和n1,計算最大公約數,每一個計算結果應占單獨一行。
orm

Sample Input
6 5 18 12
Sample Output
1
6
遞歸

 

CODE:ip

#include <stdio.h>
int f(int m,int n)
{
    int k;
    k=m%n;
    while(k!=0)
    {
        m=n;
        n=k;
        k=m%n;
    }
    return n;
}
int main()
{
    int a,b,t,max;
 
    for(; scanf("%d%d",&a,&b)!=EOF;)
    {
        if(a<b)
        {
            t=a;
            a=b;
            b=t;
        }
        max=f(a,b);
        printf("%d\n",max);
    }
    return 0;
}
歐幾里得的擴展:it

 大意:對於不徹底爲 0 的非負整數 a,b,gcd(a,b)表示 a,b 的最大公約數,必然存在整數對 x,y ,使得 gcd(a,b)=ax+by。

例題:

 

青蛙的約會

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

code:

#include <iostream>
#include <cstdio>
#define MAXN 10000
#define LL long long
using namespace std;
LL extended_gcd(LL a,LL b,LL &x,LL &y) //返回值爲gcd(a,b)
{
    LL ret,tmp;
    if (b==0)
    {
        x=1,y=0;
        return a;
    }
    ret=extended_gcd(b,a%b,x,y);
    tmp=x;
    x=y;
    y=tmp-a/b*y;
    return ret;
}
int main()
{
    LL x,y,m,n,L;
    while (scanf("%lld %lld %lld %lld %lld",&x,&y,&m,&n,&L)!=EOF)
    {
        LL a=m-n,b=L,c=y-x;
        if (a<0) a=n-m,c=x-y;
        LL re1,re2;
        LL d=extended_gcd(a,b,re1,re2);
        LL r1=c*re1/d;
        LL r2=c*re2/d;
        if (r1*d!=c*re1||r2*d!=c*re2) //c若不是gcd(a,b)的整數倍,則無解。
            printf("Impossible\n");
        else
        {
            r1=r1%(L/d);  //求最小正整數解
            if (r1<0) r1+=L/d;
            printf("%lld\n",r1);
        }
    }
    return 0;
}
相關文章
相關標籤/搜索