扩展欧几里得(乘法逆元)

来源:互联网 发布:mac有什么好用的软件 编辑:程序博客网 时间:2024/06/05 19:14

百度百科:扩展欧几里得http://baike.baidu.com/link?url=wFOWllqYIDKw1sHLTeJ-MOFHr6RLwP-3RwWroNS5xFpJq-Z3dDj2WcpvyF2dzixgIEM4aRdId3vZsA78w5CkP_

任意整数和0的公约数是该整数的所有约数它们的最大公约数为该整数本身因为0被所有非0整数整除,所以任意非零的整数都是0的约数


欧几里得算法:

单纯求两个数的最大公约数的代码(递归求法):

下面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。

#include<iostream>
#include<algorithm>
using namespace std;
int gcd(int a,int b)
{
    if(b==0){
        return a;
    }
    else{
        return gcd(b,a%b);
    }
}
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        cout<<gcd(a,b)<<endl;
    }
    return 0;
}


扩展算法:

一.在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd(a, b) =d(解一定存在,根据数论中的相关定理)

对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在无数组整数对 x,y ,使得 gcd(a,b)=ax+by。
(因为当b==0时,y的值是可以任意取的)

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int x,y,d;
void extend_Ebuild(int a,int b)
{
    if(b==0){
        x=1;
        y=0;
        d=a;
        return;
    }
    else{
        extend_Ebuild(b,a%b);
        int temp=x;//此时的x,y里面的值是上一步的数据(递归靠下面的数据),现在转换成对应当前gcd(int a,int b)的x,y的值,
        x=y;
        y=temp-(a/b)*y;
    }
}
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        extend_Ebuild(a,b);
        printf("%d = %d * %d + %d * %d\n",d,a,x,b,y);
    }
    return 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,若 c mod Gcd(a, b)=0,则该方程存在整数解,否则不存在整数解。即:(p/k)*a+(q/b)*b=c/k,如果c/k==gcd(a,b),则该方程存在整数解,否则不存在整数解。

至于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的所有整数解。

0 0
原创粉丝点击