1 long long quickpow(long long a,long long b){ 2 if(b<0) return 0; 3 long long ret=1; 4 a%=mod; 5 while(b){ 6 if(b & 1 ) ret = ( ret *a ) % mod 7 b>>=1; 8 a = (a * a)% mod; 9 } 10 return ret; 11 } 12 long long inv(long long a){ 13 return quickpow(a,mod-2); 14 }
展轉相除法:ios
能夠來這看看(回溯獲得方程解):https://baike.baidu.com/item/展轉相除法/4625352?fr=aladdin#4算法
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <ctype.h> 5 #include<string.h> 6 #include <math.h> 7 #include<algorithm> 8 using namespace std; 9 typedef long long ll; 10 void extgcd(ll a,ll b,ll& d,ll& x,ll& y) 11 { 12 if(!b) 13 { 14 d=a; 15 x=1; 16 y=0; 17 } 18 else 19 { 20 extgcd(b,a%b,d,y,x); 21 y-=x*(a/b); 22 } 23 } 24 int ModularInverse(int a,int b) 25 { 26 27 ll d,x,y; 28 extgcd(a,b,d,x,y); 29 return d==1?(x+b)%b:-1; //返回的結果就是(1/a)mod(b)的結果 30 // complete this part 31 } 32 int main() 33 { 34 printf("%d\n",ModularInverse(2,3));//結果是2 35 /* 36 2*x+3*y=1mod(3) //那個x就是(1/2)mod(3)的結果,y的話不用管,由於3*y取模於3都是0 37 */ 38 return 0; 39 }
可是對於要求好多數的逆元的題目,這樣寫會超時ide
咱們還有線性求逆元的方法 ui
來看帶餘除法 式子 p=k*i+r this
咱們能夠寫成 k*i+r≡0(mod p) spa
式子兩邊同乘 i-1*r-1 (i-1,r-1皆爲模p意義下的逆元) 3d
因此咱們有 k*r-1+i-1≡0(mod p) blog
i-1≡-k*r-1(mod p)string
i-1≡-(p/i)*(p%i)-1(mod p)it
因此i-1能夠用(p%i)-1推出,因此就能夠用遞推式求出來1到i之間全部數的逆元
代碼:
1 //一、線性求逆元 2 int inv[MAXN]; 3 void INV(int a,int p)//線性求到a的逆元 4 { 5 inv[1] = 1; 6 for (int i=2; i<=a; ++i) 7 inv[i] = (-(p/i))*inv[p%i]%p; 8 } 9 10 //二、單獨求某個值的逆元 11 int INV(int a)//線性求a的逆元 12 { 13 if (a==1) return 1; 14 return ((-(p/a)*INV(p%a))%p); 15 }