您的位置:首页 > 其它

扩展欧几里得算法

2015-09-03 18:27 281 查看
1 欧几里得算法标准代码

这个代码算的是符合a * x + b * y = gcd(a, b)的一组x, y, 同时返回了gcd(a, b)

因为a * x1 + b * y1 = gcd(a, b)

  gcd(a, b) = gcd(b, a % b)

那么a * x1 + b * y1 = gcd(b, a % b) = b * x2 + (a - a/b*b) * y2;   // a % b = a - a/b*b;而且x2, y2是更内层的

把上面得到的式子变形得 a * x1 + b * y1 = a * y2 + b * (x2 - a / b * y2);  

         对应x1 = y2, y1 = x2 - a / b * y2;

里面一层有返回值的时候想着返回上一层就好理解了,比如对应x1 = y2, y1 = x2 - a / b * y2;可以理解为上一层的y2赋给这一层的x1,上一层的 x2 - a / b * y2赋给y1

__int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y)
{
if(b==0){
x=1;
y=0;
return a;
}
__int64 g=exGcd(b,a%b,x,y);
__int64 temp=x;
x=y;
y=temp-(a/b)*y;
return g;
}


2求 a * x + b * y = c的解

就是根据上面模板算出gcd(a, b)的同时算出a * x + b * y = gcd(a, b)的解,

然后x = x * c / gcd(a, b);   y = y * c / gcd(a, b);

#include <cstdio>
__int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y) { if(b==0){ x=1; y=0; return a; } __int64 g=exGcd(b,a%b,x,y); __int64 temp=x; x=y; y=temp-(a/b)*y; return g; }
int main()
{
__int64 a, b, c, x, y, gc;
while(scanf("%I64d%I64d%I64d", &a, &b, &c) == 3)
{
gc = exGcd(a, b, x, y);
if(c % gc)
{
printf("无解\n");
continue;
}
else
printf("%I64d %I64d\n", x*c/gc, y*c/gc);
}
}


3 求逆元

这个算法好久之前就想搞定,今天终于搞定了,好开心啊

求a在mol b下的逆元, 即求满足a * x ≡ 1 (mod b)的x   //要求a和b互质

套用扩展欧几里得模板,则苛求出来 满足 a * x + b * y = gcd(a, b)的x, 因为a,b互质,故gcd(a, b) = 1所求x即a在mod b情况下的逆元,

输出大于0且最小的答案,所以 x = (x % b + b) % b;

#include <iostream>
using namespace std;
void exgcd(int a, int b, int &x, int &y)
{
if(b==0)
{
x = 1;
y = 0;
return;
}
exgcd(b, a%b, x, y);
int t = x;
x = y;
y = t - a/b*y;
}

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