• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
L&King
有何不可!
   首页    新随笔    联系   管理    订阅  订阅

求逆元

什么叫乘法逆元?

    

    这里,我们称 x 是 a 关于 m 的乘法逆元

    这怎么求?可以等价于这样的表达式: a*x + m*y = 1

怎么求逆元?

1,扩展欧几里德算法求逆元

int ex_gcd(int a,int b,int &x,int &y){
    if(!b){
        x=1,y=0;
        return a;
    }
    int ans=ex_gcd(b,a%b,y,x);
    y-=a/b*x;
    return ans;
}
int inv(int a,int mod){
    int x,y;
    int ans=ex_gcd(a,mod,x,y);
    if(ans==1)    return (x%n+n)%n;
    return -1; 
}

 2,如果为素数,那么还可以根据费马小定理得到逆元为。

 

推导过程如下

                            

根据上式,若求ans=(a/b) mod m,可转换成求a*inv[b] mod m    (inv[b]为b的逆元:b^(m-2)  ,用快速幂求)

 

3,

现在来看一个逆元最常见问题,求如下表达式的值(已知)

 

           

 

当然这个经典的问题有很多方法,最常见的就是扩展欧几里得,如果是素数,还可以用费马小定理。

 

但是你会发现费马小定理和扩展欧几里得算法求逆元是有局限性的,它们都会要求与互素。实际上我们还有一

种通用的求逆元方法,适合所有情况。公式如下

 

          

 

现在我们来证明它,已知,证明步骤如下

 

          

4,

其实有些题需要用到模的所有逆元,这里为奇质数。那么如果用快速幂求时间复杂度为,

如果对于一个1000000级别的素数,这样做的时间复杂度是很高了。实际上有的算法,有一个递推式如下

 

                   

 

它的推导过程如下,设,那么

 

       

 

对上式两边同时除,进一步得到

 

       

 

再把和替换掉,最终得到

 

       

 

初始化,这样就可以通过递推法求出模奇素数的所有逆元了。

 

另外模的所有逆元值对应中所有的数,比如,那么对应的逆元是。

 

 

 

http://blog.csdn.net/acdreamers/article/details/8220787

posted @ 2016-07-28 14:10  L&King  阅读(275)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3