欧几里德 及 扩展欧几里德

昨晚看了一点点的数论,是一个直线上的点的例题,正好用到了欧几里德算法。于是就网搜了一下,做一些笔记,以后好留着自己看。

欧几里德算法其实就是求两个整数的最大公约数的算法,gcd函数应该都知道,gcd(a,b)就是求a,b的最大公约数。根据最大公约数的性质:gcd(a,b) = gcd(b,a) = gcd(b,a%b);

也就是我们熟悉的辗转相除法,辗转相除的代码

View Code
//非递归实现
int gcd(int a,int b)
{
if(a < b) swap(a,b);
while(b)
{
int temp = b;
b = a % b;
a = t;
}
return a;
}

//递归实现
int gcd(int a,int b)
{
if(a < b) swap(a,b);
if(b) gcd(b, a % b);
return a;
}

 


扩展欧几里德算法

扩展欧几里德是:对于不全为零的 a , b来说,必然存在整数对 x , y,使得 gcd( a, b) = a * x + b * y 成立。下面是讲如何求解 x , y 。

设 a>b。

1. 显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;

2. ab < > 0 时

设 a * x1 + b * y1 = gcd(a,b);

b * x2 + (a mod b) * y2 = gcd(b,a mod b);

根据欧几里德原理有: gcd(a,b)=gcd(b,a mod b);

则:a * x1 + b * y1 = b * x2 + (a mod b) * y2;

即:a * x1 + b * y1 = b * x2 + (a - ( a / b ) * b ) * y2 = ay * 2 + b * x2 - ( a / b ) * b * y2;

根据恒等定理得:x1 = y2; y1 =x2 - ( a / b) * y2;
代码实现

 


int exgcd(int a,int b,int &x,int &y)
{
    if(b == 0)
    {
        x = 1; y = 0; return a;
    }
    int d = exgcd(b, a % b,x,y);
    int temp = x;
    x = y;
    y = temp - a / b * y;
    return d;
}

欧几里德的一个应用就是求解 线性方程 a * x + b * y + c = 0;的解。

有上可知方程式  gcd(a , b) = a * x + b * y;可以求出一对整数对 x y 满足该方程,设 d  = gcd( a ,b);

则对于方程gcd(a , b) = a * x + b * y 变为:d = a * x + b * y  , 方程两边同时除以  d 的 1 = a * ( x / d) + b * ( y / d) ,再同时乘以 c 得 c = a * ( c * x / d ) + b * ( c * y / d) ;所以对于方程 c = a * x + b * y ; 来说,他第一组解即为:

x1 = c * x / d, y1 = c * y / d (其中 x 和 y是gcd( a,b) = a * x + b * y , 的一组整数解,d 为gcd(a,b)),

所以对于方程式    c = a * x + b * y   的任意一组解即为 n ,m 则

n = x1 + b * gcd(a,b) * t; m = y1 - a * gcd(a,b) * t; t 为任意正整数。

如果 c % gcd(a,b) != 0 则 方程 c = a * x + b * y 无解。

例题 pku 1061 http://poj.org/problem?id=1061

根据题意 设 step 青蛙跳的步数

则有 abs((x + m × t) - (y + n × t)) =  k × L ; 成立

则有 (m - n) × t - (y - x ) = k × L;

则有 (m - n ) × t  - k × L = (y - x) 

所以 令 temp = (m - n),kemp = (y - x),cemp = L;

则原式变为 temp *  t + cemp * k = kemp;

即为 a * x + b * y = c;的形式

参见代码

View Code
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 using namespace std;
 5 typedef long long ll;
 6 ll temp,kemp;
 7 int exgcd(int a,int b)
 8 {
 9     if(b == 0)
10     {
11         temp = 1;
12         kemp = 0;
13         return a;
14     }
15     ll ans = exgcd(b,a % b);
16     ll t = temp;
17     temp = kemp;
18     kemp = t - a / b * temp;
19     return ans;
20 }
21 int main()
22 {
23     ll x,y,m,n,L;
24     while(cin>>x>>y>>m>>n>>L)
25     {
26         if(m == n && x != y)
27         {
28             cout<<"Impossible\n";
29             continue;
30         }
31         ll a = m - n;
32         ll b = L;
33         ll c = y - x;
34         if(a < 0)
35         {
36             a = -a;
37             c = -c;
38         }
39         ll d = exgcd(a,b);
40         if(m == n || c % d != 0)
41         {
42             cout<<"Impossible\n";
43         }
44         else
45         {
46             b /= d;
47             c /= d;
48             ll t = c * temp;
49             cout<<(t % b + b) % b<<endl;
50         }
51     }
52     return 0;
53 }
posted @ 2012-04-12 13:42  AC_Girl  阅读(316)  评论(3编辑  收藏  举报