1. 程式人生 > 實用技巧 >逆元的三種方法

逆元的三種方法

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 }