欧几里得算法实现、正确性证明及时间复杂度分析

求最大公约数的最常用的算法是欧几里得算法,也称为辗转相除法。
问题定义为求i和j的最大公约数gcd(i,j),其中i和j是整数,不妨设i>j。
算法可以递归的表示:

1.如果j能整除i,那么gcd(i,j)=j;
2.j不能整除i,令r=i%j,那么gcd(i,j)=gcd(j,r).

  上面的算法对于i<j的情况也是可以的,实际上是做了一次交换。



使用C语言实现:

int gcd(int i, int j)
{
    int r = i % j;
    return r == 0 ? j : gcd(j, r);
}

  



算法正确性分析:

下面一步一步的切入


在证明之前先看一个说明:

对于两个数i=md,j=nd.

i、j的最大公约数是d的充要条件是:m和n互质。



再看另一个说明:

如果m和n互质,那么(m-kn)和n也互质。

这个可以用反正法:

假设(m-kn)和n不互质,那么存在一个因子e,使得(m-kn)=en。

那么m=(k+e)n,这与m、n互质的题目条件违背,所以假设不成立。

则(m-kn)和n也互质。



算法的步骤1,显然是成立的,因为这就是最大公约数的定义。

算法的步骤2:

其实算法证明的目标是r=i%j != 0时,gcd(i,j)=gcd(j,r)。

根据已知条件,设d是i、j的最大公约数,则

i=md,j=nd,其中m、n是互质的。(如果m、n不互质,d就不是最大公约数)

算法的步骤1,显然成立(最大公约数定义).关键是要证明步骤2.
设d是i和j的最大公约数,
那么i=md,j=nd,m和n互质(否则d不是最大公约数).
由r=i%j可以得到i=kj+r,k=⌊m/n⌋,k≥1(我们前面假设过i>j).
把i=md,j=nd代入得到
md=knd+r
那么
r=(m-kn)d
m-kn和m也是互质的.
所以得到d是j和r的最大公约数.

  

时间: 2024-11-05 21:49:22

欧几里得算法实现、正确性证明及时间复杂度分析的相关文章

欧几里得算法的时间复杂度

欧几里得算法, 又称辗转相除法, 用于求两个自然数的最大公约数. 算法的思想很简单, 基于下面的数论等式 gcd(a, b) = gcd(b, a mod b) 其中gcd(a, b)表示a和b的最大公约数, mod是模运算, 即求a除以b的余数. 算法如下: 输入: 两个整数a, b 输出: a和b的最大公约数 function gcd(a, b:integer):integer;    if b=0 return a;    else return gcd(b, a mod b); end

欧几里得算法求两个整数的最大公因数

unsigned int Gcd (unsigned int m,unsigned int n){ unsigned int rem; while(n>0){ rem = m % n; m = n; n = rem; } return m; } 对于m<n的情况,第一次循环m,n会交换 算法的时间复杂度计算 时间复杂度 logn 若M > N,则第一次循环交换M和N. 若想分析其时间复杂度,则要求循环次数,即生成余数的次数. 可以证明: 当M > N, 则M % N < M

[P5170] 类欧几里得算法

のすたの"类欧几里得算法"第二题 P5170 [题意]已知\(n,a,b,c\),求 \[ \begin{aligned} f_{1}(a,b,c,n)&=\sum_{i=0}^n\lfloor\dfrac{ai+b}{c}\rfloor\f_{2}(a,b,c,n)&=\sum_{i=0}^n\lfloor\dfrac{ai+b}{c}\rfloor^2\f_{3}(a,b,c,n)&=\sum_{i=0}^n\lfloor\dfrac{ai+b}{c}\rf

扩展欧几里得算法的模板实现

我居然现在还记不住扩欧的板子,我太弱啦! 扩展欧几里得算法解决的是这样的问题: 给定一个不定方程组ax+by=gcd(a,b),求他的一组整数解 先给出实现代码 void exgcd(int a,int b,int &x,int &y) { if(!b) { x=1,y=0;//gcd(a,0)显然等于1*a-0*0=a return a; } int ans=exgcd(b,a%b,x,y); int tem=x; x=y; y-=tem-(a/b)*y; return ans;} 但实

最大公约数-----欧几里得算法

欧几里得算法: 如果求两个数的最大公约数,那么最一般的求法是设置一个变量i=1,然后i不断加一,如果i加到某个数后两个数都能整除这个数了,然后把这个变量保存下来,然后最后的结果中最大的就是最大公约数. 然而这种方法时间复杂度可想而知有多高,所以一般情况瞎并不用这种方法,那么就有下面的欧几里得算法: 输入:两个数 a,b 输出:两个数的最大公约数 c 欧几里得算法:(1)找出两个数中最大的和最小的,分别为tmax.tmin, (2)不断令设置一个变量t代表tmin,tmin赋值为tmax  mod

递归算法的时间复杂度分析 转载

在算法分析中,当一个算法中包含递归调用时,其时间复杂度的分析会转化为一个递归方程求解.实际上,这个问题是数学上求解渐近阶的问题,而递归方程的形式多种多样,其求解方法也是不一而足,比较常用的有以下四种方法: (1)代入法(Substitution Method)        代入法的基本步骤是先推测递归方程的显式解,然后用数学归纳法来验证该解是否合理.        (2)迭代法(Iteration Method)        迭代法的基本步骤是迭代地展开递归方程的右端,使之成为一个非递归的和

POJ 1061 青蛙绕地球约会-数论-(解一元一次同余方程+扩展欧几里得算法)

题意:两只青蛙同向跳,起点是x,y,每次分别跳m,n米,地球周长是L,求最少跳几次相遇. 分析: 把式子写好就发现是一个一元一次同余方程.用扩展欧几里得算法来求.这题很基本得会. 代码: #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<queue> #define INF 100000

POJ 2115 for求循环次数-数论-(同余方程+扩展欧几里得算法)

题意:给定for循环的初始值,结束值和增量,还有一个模,求最少的循环次数. 分析: 读完题后应该就知道是一个同余的概念,所以就是解一个一元一次同余方程,像上题一样用扩展欧几里得算法.这题的trick点是k最大为32,那么2^32超出了int,要用long long,所以在1<<k时要这样做:1LL<<k,不然就WA了. 代码: #include<iostream> #include<cstdio> #include<algorithm> #inc

数论专题---除法表达式之高精度运算,扩展欧几里得算法

[题意描述] 给定这样一个表达式:X1/X2/X3/·····/Xk,其中Xi是正整数.除法表达式应到按照从左到右的顺序求和.但在表达式中嵌入括号可以改变计算顺序.输入表达式,判断是否可以通过加括号使得表达式最后的值为整数. [分析] 表达式可以写成E=(X1·X3·····Xk)/X2:(X1一定在分子位置,X2一定在分母位置,其它任意) 问题变为E是否为整数. 对于大数相乘,我们可以采用两种方法避免数据溢出: 1.采用素数的唯一分解定理:存储可能存在素数的个数(如何存储,用一个数组就行) 2