zoukankan      html  css  js  c++  java
  • 乘法逆元

    定义

      若在mod p意义下,对于一个整数a,有ax1 (mod p),那么这个整数x即为a的乘法逆元,同时a也为x的乘法逆元。

    求解方法

    • 费马小定理

        当ap互质并且p为质数时,满足ap-11(mod p)

        证明:

        因为

          ax1(mod p)

          ap-11(mod p)

        根据同余的性质,所以

          axap-1(mod p)

          xap-2(mod p)

        即,ap的乘法逆元为ap-2

        证毕

        所以,只用打一个快速幂就可以啦:-D

        但要注意的是此方法限制了p只能为质数

    • 解不定方程

        首先先说线性同余方程

        给定整数a,b,p,求解一个整数x满足axb (mod p),或者给出无解。

        因为未知数指数为1,所以称为线性同余方程

        axb (mod p)等价于ax-bp的倍数

        y为倍数,那么ax-b=py,移项得:ax-py=b

        又因为y可以为负数,所以改写为ax+py=b

        求解x,我们只用解不定方程即可

        此方程当且仅当gcd(a,p)整除b的时候有整数解

        具体地讲,求ap的逆元x,因为x满足ax1 (mod p)

        把它化成不定方程的形式为ax+py=1

        当且仅当gcd(a,p)=1的时候有整数解

        所以此时不必保证p一定为质数,只用保证a,p互质即可

        可以利用扩展欧几里得算法求解x

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int a,b,p;
     5 void exgcd(int a,int b,int &x,int &y){//扩欧
     6     if(b==0){
     7         x=1;
     8         y=0;
     9     }else{
    10         exgcd(b,a%b,x,y);
    11         int t=x;
    12         x=y;
    13         y=t-a/b*y;
    14     }
    15 }
    16 int gcd(int a,int b){
    17     return b==0?a:gcd(b,a%b);
    18 }
    19 int main(){
    20     cin>>a>>b>>p;
    21     int x,y;
    22     exgcd(a,p,x,y);
    23         if(b%gcd(a,p)==0){
    24              cout<<(x%p+p)%p<<endl;
    25         }else{
    26              cout<<"no solution";  
    27         }   
    28     return 0;
    29 }
    • 线性递推

        现欲求ap的逆元x(x=a-1

        设p=ak+r(1<r<i<p) k就是p/a的商(可以表示为⌊p/a⌋ r是余数

        将这个式子转化为同余式就变成了ak+r≡0 (mod p)

        同时乘a-1r-1得,r-1k+a-1≡0 (mod p)a-1后文用x代替)

        再根据同余的同加性得,x≡-r-1(mod p)

         所以 x≡-⌊p/a⌋(p%a)-1 (mod p)

        再进一步即可化为 x=(p-⌊p/a⌋)(p%a)-1 (mod p)

        于是,我们就可以愉快的用递归的方法求解a的逆元啦

        大家可能已经体会到了,这种方法在求一串连续的数的逆元时会比前面的方法快很多

        下面就举个栗子:[模板]乘法逆元

        此题就是求1~n中所有数的逆元 直接用线性递推的方法就好

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int n,p;
     5 const int maxn=3e6+5;
     6 ll inv[maxn];
     7 int main(){
     8     scanf("%d%d",&n,&p);
     9     inv[1]=1;
    10     printf("1
    ");
    11     for(int i=2;i<=n;i++){
    12         inv[i]=(ll)(p-p/i)*inv[p%i]%p;
    13         printf("%d
    ",inv[i]);
    14     }
    15     return 0;
    16 }

    【模板】乘法逆【模板】乘

     _____________ヾ(❀^ω^)ノ゙___✿✿✿________‧★,:*:‧( ̄▽ ̄)/‧:*°★*___________

  • 相关阅读:
    如何在android项目中引用project作为类库引用
    Unity3d之MonoBehaviour的可重写函数整理
    Phonegap hello world 不容易啊~!
    数据结构,到底如何用中学,学中用?
    自动化测试(1610)
    软件测试人员的发展路线
    软件测试分类
    我的第一篇博客随笔
    安装虚拟机和Linux系统的学习
    英雄联盟的游戏经验
  • 原文地址:https://www.cnblogs.com/duojiaming/p/11279725.html
Copyright © 2011-2022 走看看