您的位置:首页 > 其它

欧几里得算法与扩展欧几里得算法与逆元

2017-01-31 21:56 309 查看

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

预备知识

1.

[a,b]=|ab|(a,b)

实际上,计算最好使用lcm(a,b)=a/gcd(a,b)∗b

2.

设 a,b,c∈Z

(1)∀x∈Z,(ax+b,a)=(a,b)

(2)∀x,y∈Z,(a,b)|ax+by

3.

∀a,b∈Z,∃x0,y0∈Z

使得(a,b)=a∗x0+b∗y0

即(a,b)可以表示为a和b的整系数线性组合,x0,y0成为线性表出系数。

欧几里得算法

#include<iostream>
using namespace std;
typedef long long LL;

LL gcd(LL a,LL b)
{
LL r;
while(b!=0)
{
r=a%b;
a=b;
b=r;
}
return a;
}

int main()
{
LL a,b;
while(cin>>a>>b)
{
cout<<gcd(a,b)<<endl;
}
return 0;
}


算法为表达方便要求输入整数a>b>=0,具体实现时可利用(a,b)=(|a|,|b|)调整输入参数

欧几里得算法还可以通过递归调用实现

int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}


#include<iostream>
using namespace std;
typedef long long LL;

LL gcd(LL a,LL b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}

int main()
{
LL a,b;
while(cin>>a>>b)
{
cout<<gcd(a,b)<<endl;
}
return 0;
}


扩展欧几里得算法

#include<iostream>
using namespace std;
typedef long long LL;

//ax0+by0=(a,b)
LL extended_gcd(LL a,LL b,LL &x0,LL &y0)
{
LL x1,y1,x2,y2;
x0=1,x1=0,y0=0,y1=1;
LL q,r;
while(b!=0)
{
q=a/b;
r=a-b*q;
x2=x0-x1*q,y2=y0-y1*q;
a=b,b=r,x0=x1,y0=y1,x1=x2,y1=y2;
}
return a;
}

int main()
{
LL a,b,x0,y0;
LL ans;
while(cin>>a>>b)
{
x0=1,y0=0;
ans=extended_gcd(a,b,x0,y0);
cout<<ans<<" "<<x0<<" "<<y0<<endl;
}
return 0;
}


求逆元

#include<iostream>
using namespace std;
typedef long long LL;

//返回d=gcd(a,b);ax+by=d
LL extend_gcd(LL a,LL b,LL &x,LL &y)
{
if(a==0&&b==0) return -1;//无最大公约数
if(b==0) {x=1;y=0;return a;}
LL d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}

//求逆元
//ax=1(mod n)
LL mod_reverse(LL a,LL n)
{
LL x,y;
LL d=extend_gcd(a,n,x,y);
if(d==1) return (x%n+n)%n;
else return -1;
}

int main()
{
LL a,n;
while(cin>>a>>n)
{
cout<<mod_reverse(a,n)<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: