逆元的三种方法

1、exgcd
推导:
  $b$*$x$=1($mod{p}$)
  $\rightarrow$$b$*$x$+$p$*$y$=1

代码:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 using namespace std;
 5 int x,p;
 6 int exgcd(int a,int b,int &x,int &y){
 7   if (!b){x=1;y=0;return a;}
 8   int ans=exgcd(b,a%b,y,x);
 9   y-=(a/b)*x;
10   return ans;
11 }
12 int getnum(int a,int mod){
13   int x,y;
14   int d=exgcd(a,mod,x,y);
15   if (d==1) return (x%mod+mod)%mod;
16   else return -1;
17 }
18 int main(){
19   scanf ("%d",&p);
20   for (int i = 1;i <= 8;i++){
21     cout<<getnum(i,p)<<endl;
22   }
23   return 0;
24 }

2、费马小定理
费马小定理:若$p$为素数,则有$a^{p-1}$=1($mod{p}$)
              $\rightarrow$$a^{p-2}$*a=1($mod{p}$)
$a^{p−2}$就是a在$mod{p}$意义下的逆元啦。

代码:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 using namespace std;
 5 int p;
 6 int qpow(int a,int p,int mod){
 7   int ans=1,tmp=a%mod;
 8   while (p){
 9     if (p%2==1) ans=ans*tmp%mod;
10     tmp=tmp*tmp%mod;
11     p>>=1;
12   }
13   return ans;
14 }
15 int getnum(int a,int mod){
16   return qpow(a,mod-2,mod);
17 }
18 int main(){
19   scanf ("%d",&p);
20   for (int i = 1;i <= 10;i++){
21     cout<<getnum(i,p)<<endl;
22   }
23   return 0;
24 }

3、线性求逆元

代码:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 using namespace std;
 5 int n,p,inv[1000];
 6 void getnum(int mod){
 7   inv[1]=1;
 8   for (int i = 2;i <= n;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
 9 }
10 int main(){
11   scanf ("%d%d",&n,&p);
12   getnum(p);
13   for (int i = 1;i <= n;i++) cout<<inv[i]<<endl;
14   return 0;
15 }

 

posted @ 2020-09-11 09:34  小又又  阅读(360)  评论(1编辑  收藏  举报