ACM数论基础之扩展欧几里德详细证明.docx
- 文档编号:6409638
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:12
- 大小:19.99KB
ACM数论基础之扩展欧几里德详细证明.docx
《ACM数论基础之扩展欧几里德详细证明.docx》由会员分享,可在线阅读,更多相关《ACM数论基础之扩展欧几里德详细证明.docx(12页珍藏版)》请在冰豆网上搜索。
ACM数论基础之扩展欧几里德详细证明
ACM数论基础之扩展欧几里德算法
欧几里德算法概述:
欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。
其计算原理依赖于下面的定理:
gcd函数就是用来求(a,b)的最大公约数的。
gcd函数的基本性质:
gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)
欧几里得算法的公式表述
gcd(a,b)=gcd(b,amodb)
证明:
a可以表示成a=kb+r,则r=amodb
假设d是a,b的一个公约数,则有
d|a,d|b,而r=a-kb,因此d|r
因此d是(b,amodb)的公约数
假设d是(b,amodb)的公约数,则
d|b,d|r,但是a=kb+r
因此d也是(a,b)的公约数
因此(a,b)和(b,amodb)的公约数是一样的,其最大公约数也必然相等,得证
欧几里德算法的C++语言描述
intGcd(inta,intb)
{
if(b==0)
returna;
returnGcd(b,a%b);
}
当然你也可以写成迭代形式:
intGcd(inta,intb)
{
while(b!
=0)
{
intr=b;
b=a%b;
a=r;
}
returna;
}
扩展欧几里德定理
对于不完全为0的非负整数a,b,gcd(a,b)表示a,b的最大公约数,必然存在整数对x,y,使得gcd(a,b)=ax+by。
c++语言实现
#include
usingnamespacestd;
intx,y,q;
voidextend_Eulid(inta,intb)
{
if(b==0)
{
x=1;y=0;q=a;
}
else
{
extend_Eulid(b,a%b);
inttemp=x;
x=y;
y=temp-a/b*y;
}
}
intmain()
{
inta,b;
cin>>a>>b;
if(a
swap(a,b);
extend_Eulid(a,b);
printf("%d=(%d)*%d+(%d)*%d\n",q,x,a,y,b);
return0;
}
求解x,y的方法的理解
设a>b。
1,显然当b=0,gcd(a,b)=a。
此时x=1,y=0;
2,ab<>0时
设ax1+by1=gcd(a,b);
bx2+(amodb)y2=gcd(b,amodb);
根据朴素的欧几里德原理有gcd(a,b)=gcd(b,amodb);
则:
ax1+by1=bx2+(amodb)y2;
即:
ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;
根据恒等定理得:
x1=y2;y1=x2-(a/b)*y2;
这样我们就得到了求解x1,y1的方法:
x1,y1的值基于x2,y2.
上面的思想是以递归定义的,因为gcd不断的递归求解一定会有个时候b=0,所以递归可以
结束。
扩展欧几里德算法
扩展欧几里德算法是用来在已知a,b求解一组x,y使得ax+by=Gcd(a,b)=d(解一定存在,根据数论中的相关定理)。
扩展欧几里德常用在求解模线性方程及方程组中。
下面是一个使用C++的实现:
intexGcd(inta,intb,int&x,int&y)
{
if(b==0)
{
x=1;
y=0;
returna;---很难找出一个这么实现的价值,因为扩展欧几里得还有更大的用途;个人认为定义全局数组更好,不用returnr。
}
intr=exGcd(b,a%b,x,y);
intt=x;
x=y;
y=t-a/b*y;
returnr;
}
把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。
可以这样思考:
对于a'=b,b'=a%b而言,我们求得x,y使得a'x+b'y=Gcd(a',b')
由于b'=a%b=a-a/b*b(注:
这里的/是程序设计语言中的除法)
那么可以得到:
a'x+b'y=Gcd(a',b')===>
bx+(a-a/b*b)y=Gcd(a',b')=Gcd(a,b)===>
ay+b(x-a/b*y)=Gcd(a,b)
因此对于a和b而言,他们的相对应的p,q分别是y和(x-a/b*y)
使用扩展欧几里德算法解决不定方程的办法
对于不定整数方程pa+qb=c,若cmodGcd(a,b)=0,则该方程存在整数解,否则不存在整数解。
上面已经列出找一个整数解的方法,在找到p*a+q*b=Gcd(a,b)的一组解p0,q0后, /*p*a+q*b=Gcd(a,b)的其他整数解满足:
p=p0+b/Gcd(a,b)*t
q=q0-a/Gcd(a,b)*t(其中t为任意整数)
至于pa+qb=c的整数解,只需将p*a+q*b=Gcd(a,b)的每个解乘上c/Gcd(a,b)即可
在找到p*a+q*b=Gcd(a,b)的一组解p0,q0后,应该是
得到p*a+q*b=c的一组解p1=p0*(c/Gcd(a,b)),q1=q0*(c/Gcd(a,b)),p*a+q*b=c的其他整数解满足:
p=p1+b/Gcd(a,b)*t
q=q1-a/Gcd(a,b)*t(其中t为任意整数)
p、q就是p*a+q*b=c的所有整数解。
编程时exgcd更多用于求解“中国余数定理”相关知识举个例子比如n除以5余2除以13余3那么n最小是多少,所有的n满足什么条件?
n(min)=42
n=42+k*65
欧几里德算法的扩展
扩展欧几里德算法不但能计算(a,b)的最大公约数,而且能计算a模b及b模a的乘法逆元,用C语言描述如下:
intgcd(inta,intb,int&ar,int&br)
{
intx1,x2,x3;
inty1,y2,y3;
intt1,t2,t3;
if(0==a)
{//有一个数为0,就不存在乘法逆元
ar=0;
br=0;
returnb;
}
if(0==b)
{
ar=0;
br=0;
returna;
}
x1=1;
x2=0;
x3=a;
y1=0;
y2=1;
y3=b;
intk;
for(t3=x3%y3;t3!
=0;t3=x3%y3)
{
k=x3/y3;
t2=x2-k*y2;
t1=x1-k*y1;
x1=y1;
x2=y2;
x3=y3;
y1=t1;
y2=t2;
y3=t3;
}
if(y3==1)
{
//有乘法逆元
ar=y2;
br=x1;
return1;
}
else
{
//公约数不为1,无乘法逆元
ar=0;
br=0;
returny3;
}
}
扩展欧几里德算法对于最大公约数的计算和普通欧几里德算法是一致的。
计算乘法逆元则显得很难明白。
我想了半个小时才想出证明他的方法。
首先重复拙作整除中的一个论断:
如果gcd(a,b)=d,则存在m,n,使得d=ma+nb,称呼这种关系为a、b组合整数d,m,n称为组合系数。
当d=1时,有ma+nb=1,此时可以看出m是a模b的乘法逆元,n是b模a的乘法逆元。
为了证明上面的结论,我们把上述计算中xi、yi看成ti的迭代初始值,考察一组数(t1,t2,t3),用归纳法证明:
当通过扩展欧几里德算法计算后,每一行都满足a×t1+b×t2=t3
第一行:
1×a+0×b=a成立
第二行:
0×a+1×b=b成立
假设前k行都成立,考察第k+1行
对于k-1行和k行有
t1(k-1)t2(k-1)t3(k-1)
t1(k)t2(k)t3(k)
分别满足:
t1(k-1)×a+t2(k-1)×b=t3(k-1)
t1(k)×a+t2(k)×b=t3(k)
根据扩展欧几里德算法,假设t3(k-1)=jt3(k)+r
则:
t3(k+1)=r
t2(k+1)=t2(k-1)-j×t2(k)
t1(k+1)=t1(k-1)-j×t1(k)
则
t1(k+1)×a+t2(k+1)×b
=t1(k-1)×a-j×t1(k)×a+
t2(k-1)×b-j×t2(k)×b
=t3(k-1)-jt3(k)=r
=t3(k+1)
得证
因此,当最终t3迭代计算到1时,有t1×a+t2×b=1,显然,t1是a模b的乘法逆元,t2是b模a的乘法逆元。
c语言实现
//扩展的欧几里德算法求乘法逆元
#include
intExtendedEuclid(intf,intd,int*result);
intmain()
{
intx,y,z;
z=0;
printf("输入两个数:
\n");
scanf("%d%d",&x,&y);
if(ExtendedEuclid(x,y,&z))
printf("%d和%d互素,乘法的逆元是:
%d\n",x,y,z);
else
printf("%d和%d不互素,最大公约数为:
%d\n",x,y,z);
return0;
}
intExtendedEuclid(intf,intd,int*result)
{
intx1,x2,x3,y1,y2,y3,t1,t2,t3,q;
x1=y2=1;
x2=y1=0;
x3=(f>=d)?
f:
d;
y3=(f>=d)?
d:
f;
while
(1)
{
if(y3==0)
{
*result=x3;/*两个数不互素则result为两个数的最大公约数,此时返回值为零*/
return0;
}
if(y3==1)
{
*result=y2;/*两个数互素则resutl为其乘法逆元,此时返回值为1*/
return1;
}
q=x3/y3;
t1=x1-q*y1;
t2=x2-q*y2;
t3=x3-q*y3;
x1=y1;
x2=y2;
x3=y3;
y1=t1;
y2=t2;
y3=t3;
}
}
扩展欧几里德算法
欧几里德算法
欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。
其计算原理依赖于下面的定理:
定理:
gcd(a,b)=gcd(b,amodb)
证明:
a可以表示成a=kb+r,则r=amodb
假设d是a,b的一个公约数,则有
d|a,d|b,而r=a-kb,因此d|r
因此d是(b,amodb)的公约数
假设d是(b,amodb)的公约数,则
d|b,d|r,但是a=kb+r
因此d也是(a,b)的公约数
因此(a,b)和(b,amodb)的公约数是一样的,其最大公约数也必然相等,得证
欧几里德算法就是根据这个原理来做的,其算法用C++语言描述为:
intGcd(inta,intb)
{
if(b==0)
returna;
returnGcd(b,a%b);
}
当然你也可以写成迭代形式:
intGcd(inta,intb)
{
while(b!
=0)
{
intr=b;
b=a%b;
a=r;
}
returna;
}
本质上都是用的上面那个原理。
补充:
扩展欧几里德算法是用来在已知a,b求解一组p,q使得p*a+q*b=Gcd(a,b)(解一定存在,根据数论中的相关定理)。
扩展欧几里德常用在求解模线性方程及方程组中。
下面是一个使用C++的实现:
intexGcd(inta,intb,int&x,int&y)
{
if(b==0)
{
x=1;
y=0;
returna;
}
intr=exGcd(b,a%b,x,y);
intt=x;
x=y;
y=t-a/b*y;
returnr;
}
把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。
可以这样思考:
对于a'=b,b'=a%b而言,我们求得x,y使得a'x+b'y=Gcd(a',b')
由于b'=a%b=a-a/b*b(注:
这里的/是程序设计语言中的除法)
那么可以得到:
a'x+b'y=Gcd(a',b')===>
bx+(a-a/b*b)y=Gcd(a',b')=Gcd(a,b)===>
ay+b(x-a/b*y)=Gcd(a,b)
因此对于a和b而言,他们的相对应的p,q分别是y和(x-a/b*y)
补充:
关于使用扩展欧几里德算法解决不定方程的办法
对于不定整数方程pa+qb=c,若cmodGcd(a,b)=0,则该方程存在整数解,否则不存在整数解。
上面已经列出找一个整数解的方法,在找到p*a+q*b=Gcd(a,b)的一组解p0,q0后,/*p*a+q*b=Gcd(a,b)的其他整数解满足:
p=p0+b/Gcd(a,b)*t
q=q0-a/Gcd(a,b)*t(其中t为任意整数)
至于pa+qb=c的整数解,只需将p*a+q*b=Gcd(a,b)的每个解乘上c/Gcd(a,b)即可。
*/有问题
在找到p*a+q*b=Gcd(a,b)的一组解p0,q0后,应该是
得到p*a+q*b=c的一组解p1=p0*(c/Gcd(a,b)),q1=q0*(c/Gcd(a,b)),p*a+q*b=c的其他整数解满足:
p=p1+b/Gcd(a,b)*t
q=q1-a/Gcd(a,b)*t(其中t为任意整数)
p、q就是p*a+q*b=c的所有整数解。
“有问题”的一段已经标出
也就是在得出p*a+q*b=Gcd(a,b)的解后是先乘上c/Gcd(a,b)从而导出p*a+q*b=c的其他整数解,
还是先导出p*a+q*b=Gcd(a,b)的其他整数解再乘上c/Gcd(a,b)。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACM 数论 基础 扩展 欧几里德 详细 证明