用C语言编制的求模逆元的扩展欧几里德算法,只要能基本上实现这个功能就行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用C语言编制的求模逆元的扩展欧几里德算法,只要能基本上实现这个功能就行相关的知识,希望对你有一定的参考价值。

在线等 很着急

    扩展欧几里德算法是用来在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd(a, b) =d(解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及方程组中。

    下面是一个使用C语言的实现:

    intexGcd(int a,int b,int &x,int &y)

        if(b==0)    //当b==0时,得到解
        
            x=1;y=0;
            return a;
        
        intr=exGcd(b,a%b,x,y);//递归调用自身,求解
        intt=x;x=y;y=t-a/b*y;
        return r;

参考技术A 转自 http://hi.baidu.com/forverlin1204/blog/item/dadfc612faddbfdbf6039e5f.html

#include<iostream>
using namespace std;
//举例 3x+4y=1 ax+by=1
//得到一组解x0=-1,y0=1 通解为x=-1+4k,y=1-3k
inline __int64 extend_gcd(__int64 a,__int64 b,__int64 &x,__int64 &y)//ax+by=1返回a,b的gcd,同时求的一组满足题目的最小正整数解

__int64 ans,t;
if(b==0)x=1;y=0;return a;
ans=extend_gcd(b,a%b,x,y);t=x;x=y;y=t-(a/b)*y;
return ans;

//(a/b)%mod=c 逆元为p,(p*b)%mod=1
//(a/b)*(p*b)%mod=c*1%mod=c
// (p*b)%mod=1 等价于 p*b-(p*b)/mod*mod=1其中要求p,b已知 等价于 ax+by=1
//其中x=p(x就是逆元),y=p/mod,a=b,b=b*mod 那么调用extend_gcd(b,b*mod,x,y)即可求(a/b)%mod的逆元等价于a*p%mod
int main()

__int64 a,b,x,y,c,gcd,mod,p;//ax+by=c
while(cin>>a>>b>>c)

gcd=extend_gcd(a,b,x,y);
if(c%gcd)cout<<"无解!"<<endl;continue;
cout<<"x="<<x*c/gcd<<" y="<<y*c/gcd<<endl;

return 0;
本回答被提问者和网友采纳

数论及其应用——欧几里得算法

  欧几里得是数论当中最基本的定理,以其为基础的拓展欧几里得算法在解决同余方程、求模逆元等问题。

 

  首先来介绍几个概念,数论当中一些基本的概念其实在小学就学过,但是很长一段时间并没有用到它们,因此这里再拿出来温习一下。

  我们常常用a|b来表示b能够整除a(b > a),即b/a是整数,但是“|”在使用的过程中容易和绝对值、几何定义符、条件概率混淆,所以,这里我们用a\b来表示a能够整除b。

 

  约数:如果b\a,则称b是a的约数。

  倍数:如果b\a,则称a是b的倍数。

  最大公约数:gcd(a,b) = max{k | k\a 且k\b}。

  最小公倍数:lcm(a,b) = min{k | k>0 , a\k 且b\k}

 

  那么现在我们面临一个重要的问题,给出一系列数字,我们想要通过一个程序得到这些数字的最大公约数或者最小公倍数, 应该怎么做呢?

  容易想到穷举,当然,容易想到的代价是牺牲大量的时间,我们需要用更好的思维去简化这个过程。

 

  计算最大公约数的方法:欧几里得算法.

  n>m,gcd(m,n) = gcd(n % m, m) , gcd(0,n) = n.

  证明:

  n = qm + r,r>0。
  我们假设存在这样一个d,它是m、n的公因子,即d\a 且 d\b。

  可以看到r = n - qm ,假如c = xa + yb,且d\a,d\b,那么d\c。这里是同样道理,所以d\r,加上之前的d\b,定理成立.


    

   基于这个结论,我们在求解gcd(m,n)(n > m)的时候,可以转而去求gcd(n % m , m).

  求gcd(n % m , m)的时候,可以转而去求gcd(m%(n%m) , n%m)

  ……

  这就形成了一个递归性质的求解过程,可能在说这个递归的流程你就会质疑,上面的证明过程我们给出的公因子相同,但是如何保证其是最大公因子(最大公约数)呢?想象一下这个递归过程,如果保证了递归的最后一层得到的公因子d是最大公因数,那么最终我们就会返回一个最大公约数。

那么现在我们要解决的一个主要问题变成了:递归的最底层是什么呢?或者说,递推到什么程度开始“归”呢?想象一下,递推下去的终点,gcd(a,b)的a、b中必然有一个数是0,然后用我们在定理中定义的:gcd(a,0) = a.a其实就是整个递归过程中的解,这保证了递归过程中传递的约数一直是最大公约数。

而在设计递归程序的时候,为了得到返回值(即上一段的a),我们规定gcd(a,b)函数a>b,这样返回结果即为:gcd(a,0),返回a.

 参考代码如下:

#include<cstdlib>

#include<iostream>

using namespace std;

long long gcd(int a , int b)

{

     if(b == 0)

          return a;

     else  return gcd(b , a%b);

}

 

以上是关于用C语言编制的求模逆元的扩展欧几里德算法,只要能基本上实现这个功能就行的主要内容,如果未能解决你的问题,请参考以下文章

扩展欧几里得算法求逆元算法结果是负数

素数定理-欧几里得算法-乘法逆元

【总结】逆元的求法

(数论)简单总结求逆元的几种方法

解模逆元? x

数论及其应用——欧几里得算法