欧几里得辗转相除法及费马小定理

欧几里德辗转相除法
2008-06-11 21:26

【转】关于欧几里德辗转相除法的证明,总觉得没那么地道。不管了,先转过来再说。后面的证明嘛,说实话,没太仔细看呢!似乎又想起来沈老师讲离散时的音容笑貌……

欧几里德辗转相除法是最大公约数(greatest common divisor)的求法。
C++代码如下:
int gcd(int a, int b)
{
     if(b == 0)
         return a;
     else
         return gcd(b, a%b);   
}
这个算法就是利用了gcd(a, b) = gcd(b, a mod b)。
证明:
对于a, b的任意公约数r,则r|a, r|b。
那么a mod b = a - [a/b]*b,[a/b]是取整函数
由于r|a, r|b所以r|(a mod b)。
对于b, a mod b的公约数r,则r|b, r|(a mod b)
a = a mod b + [a/b]*b, 所与r|a。这样就证明了
a,b的公约数和b, a mod b完全相同,则最大公约数也相同。


费马小定理
(1)p为素数, 则p|(a^p - a)
(2)p为素数,gcd(a, p) = 1, 则 p|(a^(p-1)-1)
证明:
对于(2),p是素数,a是整数且gcd(a,p)=1即他们的最大公约数是1。
由于a, 2a, 3a, ……,(p-1)a 模p的余数都不相同。
否则若(i*a) mod p=(j*a) mod p
其中 1 =< i < j <= p-1 则p|(j-i)*a, 而gcd(a,p)=1,
那么p|(j - i),这是不可能的,所以a, 2a, 3a, ……, (p-1)a对p的余数
取遍1,2,……p-1。
所以a*2a*3a*4a*……*(p-1)a对p的余数等于1*2*……(p-1)对p的余数。
这是由于性质:a mod p = x, b mod p = y, 那么(a*b) mod p = (x*y) mod p。
1*2*……(p-1)*a^(p-1) mod p = (p-1)! mod p
((a^(p-1) - 1)*(p-1)! + (p-1)!)mod p = (p-1)! mod p
则(a^(p-1) - 1)*(p-1)! mod p = 0
由于p是素数,gcd(p, (p-1)!)=1
所以a^(p-1) - 1 mod p = 0
就是 p|(a^(p-1) - 1)。因此(2)得证。
对于(1) 若gcd(a,p) ≠ 1,那么由于p是素数必然p|a 因此p|a*(a^(p - 1) - 1)显然得证。
如果gcd(a,p) = 1, 则由(2)得p|(a^(p-1)-1)因此因此p|(a^(p - 1) - 1)*a显然得证。

欧拉函数是指:对于一个正整数n,小于n且和n互质的正整数的个数,记做:φ(n)
欧拉定理:gcd(a, n) = 1,则a^φ(n) ≡ 1 mod n
对于互质的整数a和n,有a^φ(n) ≡ 1 mod n
证明:
     首先证明下面这个命题:
     对于集合Z = {X1,X2,...,Xφ(n)},Xi为第i个小于n且和n互质的正整数
     考虑集合
     S = {aX1 mod n,aX2 mod n,...,aXφ(n) mod n}
     则S = Z
     证明:
     a, n互质,Xi与n互质,那么aXi与n互质
     对于Z中两个元素Xi和Xj,如果Xi ≠ Xj
     则aXi mod n ≠ aXj mod n,若aXi mod n = aXj mod n,
     那么a(Xi - Xj) mod n = 0, a, n互质那么Xi - Xj mod n = 0 由于
      0 < Xi, Xj < n显然不可能。因此S中的元素各不相同,这样S中含有φ(n)个与n互
    质的正整数,且满足每个元素小于n所以,很明显,S = Z        
     既然这样,那么
     (aX1 × aX2×...×aXφ(n))mod n
      = (aX1 mod n × aX2 mod n × ... × aXφ(n) mod n)mod n
      = (x1 × x2 × ... × xφ(n))mod n
      考虑上面等式左边和右边
      最左边等于(a^φ(n) × (x1 × x2 × ... × xφ(n)) mod n
      最右边等于(x1 × x2 × ... × xφ(n))mod n
      得到(a^φ(n) - 1)(x1 × x2 × ... × xφ(n)) mod n = 0
      而(x1 × x2 × ... × xφ(n))mod n 和 n互质,所以 a^φ(n) ≡ 1 mod n
推论:当n为素数时,φ(n) = n - 1, a^(n - 1) - 1 mod n = 0 就是费马小定理(2)
模p乘法逆元
对于整数a、p,如果存在整数b,满足a*b mod p =1,则说,b是a的模p乘法逆元。
定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1
证明:
首先证明充分性
如果gcd(a,p) = 1,根据欧拉定理,a^φ(p) ≡ 1 mod p,因此
显然a^(φ(p)-1) 是a的模p乘法逆元。
再证明必要性
假设存在a模p的乘法逆元为b, a*b ≡ 1 mod p
则a*b = k*p + 1,所以1 = a*b - k*p
因为gcd(a,p) = d
所以d | 1
所以d只能为1
扩展欧几里德定理
如果gcd(a, b) = d, 那么一定存在整数x,y 满足a*x + b*y = d

证明,可以设a = p*d, b = q*d,显然gcd(p, q) = 1
a*x + b*y = p*d*x + q*d*y 若要a*x + b*y = d
必需p*x + q*y = 1,由gcd(p, q) = 1 则p^φ(q) ≡ 1 mod q
令x = p^(φ(q) - 1) 也就是x是p的模q逆元,则p*x - 1 = p^φ(q) - 1 mod q
= 0, 那么y = (p^φ(q) - 1)/q显然是整数, 当然也可以y = q^(φ(p) - 1),那
么x = (q^φ(p) - 1)/p,注意到x, y有无数组解。
注意到对于gcd(a,b) = d 我们对(a, b)用欧几里德辗转相除会最终得到
(d, 0)此时对于把a =d, b = 0 带入a*x + b*y = d,显然x = 1,y可以为任意值,
这里y可以为任意值就意味着解会有无数个。我们可以用a = d, b = 0的情况逆推出来
任何gcd(a, b) = d 满足a*x + b*y = d的解。如果x0, y0是b*x + (a%b)*y = d 的解,那么对于a*x + b*y = d的解呢?
b*x + (a%b)*y = d => b*x + (a - [a/b]*b)*y = a*y + b*(x - [a/b]*y),所以a*x + b*y = d的解x1 = y0, y1 = x0 - [a/b]*y0; 这样我们可以程序迭带了。
void extended_gcd(int a, int b, int &x, int &y)
{
  
   if(b == 0)
      {
        x = 1;
        y = 0; //any integer is ok;
       }
       else
       {
         int t;
         extended_gcd(b, a%a, x, y);
         t = x;
         x = y;
         y = t - (a/b)*y;
       }  
}
 
 
以下为从浙江工业大信息工程分院 首 页 > 论 坛 > ACM程序设计专栏17 复制的
 
主题:欧几里德算法(辗转相除法)求两个数的最大公约数 您是本帖的第 251 个阅读者
seanchen88

普通会员
发帖:10
主页:http://  EMAIL:seanchen118-zc@yahoo.com.cn  QQ号码:249901108  IP地址:未知  来自地区:未知 楼 主
 欧几里德算法(辗转相除法)求两个数的最大公约数
欧几里德算法(辗转相除法)求两个数的最大公约数的步骤如下:
先用小的一个数除大的一个数,得第一个余数;
再用第一个余数除小的一个数,得第二个余数;
又用第二个余数除第一个余数,得第三个余数;
这样逐次用后一个数去除前一个余数,直到余数是0为止。那么,最后一个除数就是所求的最大公约数(如果最后的除数是1,那么原来的两个数是互质数)。
例如求1515和600的最大公约数,
第一次:用600除1515,商2余315;
第二次:用315除600,商1余285;
第三次:用285除315,商1余30;
第四次:用30除285,商9余15;
第五次:用15除30,商2余0。
1515和600的最大公约数是15
不在风里来,就在雨里去
2007-10-11 15:04
 
 
 
特此"百度知道"之:
Euclid
欧几里德算法又称辗转相除法,用于计算两个整数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++语言描述为:

void swap(int & a, int & b)
{
int c = a;
a = b;
b = c;
}
int gcd(int a,int b)
{
if(0 == a )
{
return b;
}
if( 0 == b)
{
return a;
}
if(a > b)
{
swap(a,b);
}
int c;
for(c = a % b ; c > 0 ; c = a % b)
{
a = b;
b = c;
}
return b;
}
参考资料:internet ...

当然还有个递归版的, 其实gcd函数一般不会递归调用很多次, 所以递递归还是不错的:
int gcd(int a, int b)
{
    if (b > 0)
    {
        return gcd(b, a % b);
    }
    return a;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值