逆元的三种方法
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 }