//欧几里得算法求最大公约数
int gcd(int m,int n)
{int u0=m,u1=n,t;if( u0<u1 )// 保证u0>=u1u0^=u1,u1^=u0,u0^=u1;while(u0%u1){t=u1;u1=u0%u1;u0=t;}return u1;
}
//递归版本
int gcd(int m, int n)
{return n==0?m:gcd(n,m%n);
}
//扩展欧几里得算法求ax+by==gcd(a,b)的解,其中g是最大公约数,此算法根据结论gcd(a,b)是a和b的最小的正线性组合得出(特殊情况,当gcd(a,b)为1时候,解x为a的逆元)
void gcdex(int m,int n, int& g,int & x,int& y)
{if(n==0)        {//gcd(m,0)=1*m-0*0=mg=m; x=1; y=0;}else            {gcdex(n,m%n,g,y,x);     y-=x*(m/n);}
}
//求最小公倍数
//求n个数最小公倍数,(除去所有的公约数,就成了最小公倍)
int lcm(int val[],int n)
{int res=1;for (int i = 0;i < n;i ++)for (int j = i + 1;j <= n;j++)if (val[j] % val[i] == 0)val[j] /= val[i];for(int j=0; j<n; j++)res*=val[j];return res;
}

//以下介绍来自网络

RSA算法中利用欧几里得算法求d详细过程

RSA是第一个也是使用的最广泛的公钥加密算法,在1978年由R.Rivest、AdiShamir和Adleman三人发明,并以他们的名字命名。RSA算法的安全性基于大数因子分解的困难性,下面介绍一下它的基本原理:


1、生成公钥和私钥

(1)选取两个大素数:p和q;
(2)计算n=p*q;
(3)计算小于n并且与n互质的整数的个数,即欧拉函数Ø(n)=(p-1)*(q-1);
(4)随机选择加密密钥e,使1<e<Ø(n),且与Ø(n)互质;
(5)最后,利用Euclid(欧几里得)算法计算解密密钥d,使其满足ed=1(mod Ø(n))。

然后将(e,n)公开,即为公钥PK,私人保存好d,即为私钥SK;

2、加密

将明文m分解成等长数据块m1,m2,……,mi。加密时,按如下公式进行计算即可:

ci=(mie(mod n),密文c则由c1,c2,……ci组成。

3、解密

与加密一样,按如下公式进行计算:

mi=(cid(mod n),明文m则由m1,m2,……,mi组成。


以上就是RSA算法的公私钥产生、加密和解密的过程。整个过程中,最难理解的部分应是1.5中的求私钥d,很多课本提到的都是用欧几里得算法,但并未给出具体的计算过程,下面本人就通过一个实例向大家介绍欧几里得算法在RSA中的应用。

例:令p=47,q=71,求用RSA算法加密的公钥和私钥。

计算如下:

(1)n=pq=47*71=3337;
(2)Ø(n)=(p-1)*(q-1)=46*70=3220;
(3)随机选取e=79(满足与3220互质的条件);
(4)则私钥d应该满足:79*d mod 3220 = 1;

那么这个式子(4)如何解呢?这里就要用到欧几里得算法(又称辗转相除法),解法如下:

(a)式子(4)可以表示成79*d-3220*k=1(其中k为正整数);
(b)将3220对79取模得到的余数60代替3220,则变为79*d-60*k=1;
(c)同理,将79对60取模得到的余数19代替79,则变为19*d-60*k=1;
(d)同理,将60对19取模得到的余数3代替60,则变为19*d-3*k=1;
(e)同理,将19对3取模得到的余数1代替19,则变为d-3*k=1;

当d的系数最后化为1时,

令k=0,代入(e)式中,得d=1;
将d=1代入(d)式,得k=6;
将k=6代入(c)式,得d=19;
将d=19代入(b)式,得k=25;
将k=25代入(a)式,得d=1019,这个值即我们要求的私钥d的最终值。

此时,我们即可得到公钥PK=(e,n)={79,3337},私钥SK={1019,3337},后面的加密和解密直接套相应公式即可。
#include <iostream>//扩展欧几里得算法的特殊情况,求乘法逆元
unsigned inverse(unsigned prime, unsigned mod)
{unsigned res;//记录计算结果if (prime == 1)return prime;else if (prime == 0)return 0;else{res = ( mod>prime ? inverse( prime, mod%prime):inverse(prime%mod, mod) );return ( mod>prime ? ( (mod*res+1)/prime ) : ( (prime*res-1)/mod) );}
}int main()
{printf("%d",inverse(79,3220) );getchar();return 0;
}

//附上网络搜来的扩展欧几里得算法的证明

什么是GCD?
GCD是最大公约数的简称(当然理解为我们伟大的党也未尝不可)。在开头,我们先下几个定义:
①a|b表示a能整除b(a是b的约数)
②a mod b表示a-[a/b]b([a/b]在Pascal中相当于a div b)
③gcd(a,b)表示a和b的最大公约数
④a和b的线性组合表示ax+by(x,y为整数)。我们有:若d|a且d|b,则d|ax+by(这很重要!)

线性组合与GCD
现在我们证明一个重要的定理:gcd(a,b)是a和b的最小的正线性组合。
证明:
设gcd(a,b)为d,a和b的最小的正线性组合为s
∵d|a且d|b,
∴d|s。
而a mod s=a-[a/s]s
         =a-[a/s](ax+by)
         =a(1-[a/s]x)-b[a/s]y
亦为a和b的线性组合
∵a mod s<s,a mod s不能是a和b的最小的正线性组合
∴a mod s=0,即s|a
同理由s|b
∴s为a,b的公约数
∴s<=d
∵d|s
∴d=s。证毕。

由这条定理易推知:若d|a且d|b,则d|gcd(a,b)

Euclid算法
现在的问题是如何快速的求gcd(a,b)。穷举明显不是一个好方法(O(n)),所以需要一个更好的方法。
首先我们先提出一个定理:gcd(a,b)=gcd(b,a-bx)(x为正整数)。

证明:
设gcd(a,b)=d,gcd(b,a-bx)=e,则
∵d|a,d|b
∴d|a-bx
∴d|gcd(b,a-bx),即d|e
∵e|b,e|a-bx
∴e|bx+(a-bx),即e|a
∴e|gcd(a,b),即e|d
∴d=e。证毕。

这个定理非常有用,因为它能快速地降低数据规模。
当x=1时,gcd(a,b)=gcd(b,a-b)。这就是辗转相减法。
当x达到最大时,即x=[a/b]时,gcd(a,b)=gcd(b,a mod b)。这个就是Euclid算法。它是不是Euclid提出的我不知道,但听说是在Euclid时代形成的,所以就叫Euclid算法了。程序非常的简单:

functionEuclid(a,b:longint):longint;
 begin
  if b=0 then exit(a)
         else exit(Euclid(b,a mod b));
 end;

Euclid算法比辗转相减法好,不仅好在速度快,而且用起来也方便。两种算法都有一个隐含的限制:a>=b。用辗转相减法时,必须先判断大小,而Euclid算法不然。若a<b,则一次递归就会转为gcd(b,a),接着就能正常运行了。

扩展Euclid
前面我们说过,gcd(a,b)可以表示为a和b的最小的正线性组合。现在我们就要求这个最小的正线性组合ax+by中的x和y。这个可以利用我们的Euclid算法。
从最简单的情况开始。当b=0时,我们取x=1,y=0。当b≠0时呢?
假设gcd(a,b)=d,则gcd(b,a mod b)=d。若我们已经求出了gcd(b,a mod b)的线性组合表示bx'+(a mod b)y',则
gcd(a,b)=d
        =bx'+(a mod b)y'
        =bx'+(a-[a/b]b)y'
        =ay'+b(x'-[a/b]y')
那么,x=y',y=x'-[a/b]y'。这样就可以在Euclid的递归过程中求出x和y。

程序:
function gcd(a,b:longint):longint;
 var p,n,m:longint;
 begin
  if b=0 then
   begin
    x:=1;
    y:=0;
    exit(a);
   end
  else
   begin
    p:=gcd(b,a mod b);
    n:=x;
    m:=y;
    x:=m;
    y:=n-a div b*m;
    exit(p);
   end;
 end;

我们现在还有一个问题:x,y是不是确定的?答案:不是。如果x,y符合要求,那么x+bk,y-ak也符合要求。不确定的原因在于这一句:“当b=0时,我们取x=1,y=0。”实际上y可以取任何正整数。

不定方程ax+by=c
现在终于到了本文重点:解二元一次不定方程。看起来扩展Euclid算法是不定方程的一种特殊情况,实际上呢,不定方程却是用Euclid算法解的。
对 于不定方程ax+by=c,设gcd(a,b)=d,如果ax+by=c有解,则d|c(这也是许多奥数题的切入点)。所以一旦d不是c的约数,那么 ax+by=c一定无解。当d|c时,先求出ax'+by'=d=gcd(a,b)的x'和y',则x=x'*c/d,y=y'*c/d。由上一段可知, 只要ax+by=c有一个解,它就有无数个解。
Euclid算法还可以求解同余方程ax≡b(mod m)。这其实和不定方程ax+my=b没有区别。(不定方程和同余方程一般都有范围限制,这其实也很容易解决,就不说了)

欧几里得扩展欧几里得算法及相关的数学证明相关推荐

  1. 欧几里得扩展欧几里得算法

    #朴素的欧几里得算法大家应该知道 g c d ( a , b ) gcd(a,b) gcd(a,b)表示a,b的最大公约数 朴素的欧几里得算法其实就是所谓的辗转相除法 辗转相除法 g c d ( a ...

  2. 数论:欧几里得与扩展欧几里得算法

    文章目录 欧几里得算法 历史发展 表示 证明 代码 例题 扩展欧几里得算法 表示 求解方法 代码 其他定理: 例题 欧几里得算法 历史发展 欧几里得算法用来求得两个数的最大公约数,大约公元前300年首 ...

  3. 欧几里得与扩展欧几里得算法(含推导过程及代码)

    文章目录 前言 一.欧几里得算法 二.扩展欧几里得算法 2.1.认识裴蜀定理 2.2.推导ax+by=gcd(a, b)得到x与y 2.2.1.推导过程 2.2.2.代码实现 2.3.推导ax+by= ...

  4. 扩展欧几里得算法_扩展欧几里得递推算法

    欧几里得算法 表示 整数 a 与 b 的最大公约数. 若 t = a % b, 则 证明略. 递推版 gcd 算法 gcd 接受变量元组 (a, b) 作为输入,输出最大公约数 (r). 我们很难直接 ...

  5. 欧几里得和扩展欧几里得算法

    欧几里得算法 又称为辗转相除法,c语言代码如下: 分析:a,b的关系可表示为a=kb+t, 即 a-kb=t, t=a%b, 假设c为a,b的一个公约数,将a-kb=t等式两边同除c, 得 a/c-k ...

  6. 欧几里得与扩展欧几里得算法

    原博客:https://www.cnblogs.com/haveyoueverbeen/p/4612753.html 关于扩展欧几里得算法(Extended Euclidean Algorithm), ...

  7. c语言中欧几里得模乘法逆元,扩展欧几里得算法同余方程模m乘法逆元详解

    欧几里德算法: 复习:求最大公约数算法(欧几里得算法.也叫辗转相除法).欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd ...

  8. GCD LCM 欧几里得算法 扩展欧几里得算法

    欧几里得算法: 辗转相除法的关键恒等式:gcd(a,b)=gcd(b,a mod b); 边界条件:gcd(a,0)=a; //最大公约数 int gcd(int a,int b) {return b ...

  9. 扩展欧几里得算法 POJ 1061

    根据此题 整理下 扩展欧几里得 扩展欧几里得是用来判断并求 ax + by = c 是否有解及其解的数学算法 首先列出定理 1.ax + by = gcd(a,b) 2.gcd(a,b) = gcd( ...

最新文章

  1. python自学攻略-大牛整理!Python学习方法和学习路线,看完茅塞顿开!
  2. win10连接计算机,如何在win10中连接计算机和打印机
  3. Grails精华:使用Groovy SQL
  4. OpenGL浮雕效果
  5. 第8章 线性时间排序
  6. python 内置递归
  7. POJ 2353 DP
  8. TIFF图像被转换为​​JPEG格式的图像
  9. 使用switch case语句来显示月份的对应天数
  10. LeetCode-1两数之和
  11. android 65536 简书,app编译打包时的65536问题
  12. Kotlin — 使用IDEA运行第一个Kotlin程序,打印“Hello World”!
  13. 关于表数据同步使用update_time时的注意事项
  14. 宏基ec471g黑苹果_【图片】简单安装黑苹果,老爷车宏基E1-471G完整度90%,显卡声卡成功驱动【2_黑苹果吧】_百度贴吧...
  15. 技术岗网上测评-智力题
  16. idea中找到VM options选项
  17. 在家登录学校图书馆知网
  18. Spring Cloud 五大组件
  19. Python爬虫入门第一课:如何解析网页
  20. Java中getBytes()方法--使用详解

热门文章

  1. Java基础巩固Day2作业
  2. 计算机excel怎么添加实线边框,excel中单元格输入内容怎么设置自动加上实线边框...
  3. reactive() 函数
  4. iphone浏览器Safari中的数字被识别为电话号码
  5. oracle连接另外一个oracle,Oracle 连接 另一个Oracle数据库 服务器连接
  6. 安装busybox步骤
  7. 解决android键盘顶布局导致布局错乱(华为 oppo手机弹框问题)
  8. mysql Unknown error 1146
  9. 西安交大计算机考研软件工程编程题库(二十四)
  10. 抽象类(abstract class)和接口(interface)