关于乘法逆元 a*b=1( mod p ) a是b关于p的乘法逆元
(1) 解决除法不能取摸的问题
(a + b) % p = (a%p + b%p) %p (对)
(a - b) % p = (a%p - b%p) %p (对)
(a * b) % p = (a%p * b%p) %p (对)
(a / b) % p = (a%p / b%p) %p (错) 这个是不对的 关于这个的正确运算 我们可以求 b关于p的乘法逆元 x
(a / b ) % p= (a%p)*( x % p)%p; (对)
求a关于b的乘法逆元 只有gcd(a,b) 才有逆元
(1)拓展欧几里德算法
#include<bits/stdc++.h> using namespace std; void exgcd(int a,int b,int &x,int &y) { if(b==0) { x=1,y=0; return; } exgcd(b,a%b,x,y); int xx=x; x=y; y=xx-a/b*y; } int32_t main() { int a=5; int b=3; if(__gcd(a,b)==1) { int x;int y; exgcd(a,b,x,y); cout<<(x%b+b)%b<<endl; // x a guan yu b de chengfaniyuan } }
(1)费马小定理 p 都是素数 gcd(a,p)=1; a^(p-2) 与 a 互为乘法逆元 (mod p);
这样求出来的不一定是最小的逆元 取摸p就可以求出最小的了
#include<bits/stdc++.h> using namespace std; int quick(int a,int n) { int ans=1; int t=a; while(n!=0) { if(n%2==0) {n=n/2; t=t*t;} else if(n%2==1) {n--; ans*=t; } } return ans; } int32_t main() { int a=5; int b=3; if(__gcd(a,b)==1) { cout<<quick(a,b-2)%b<<endl; } }
(3)这个我也不知道 当p是个质数的时候 inv(a) = (p - p / a) * inv(p % a) % p 不证明 (下面代码来源) https://www.cnblogs.com/linyujun/p/5194184.html#3804000
#include<cstdio> typedef long long LL; LL inv(LL t, LL p)
{
//求t关于p的逆元,注意:t要小于p,最好传参前先把t%p一下 return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p; } int main(){ LL a, p; while(~scanf("%lld%lld", &a, &p)){ printf("%lld\n", inv(a%p, p)); } }
求n个数的乘法逆元 O(n)
#include<cstdio> const int N = 200000 + 5; const int MOD = (int)1e9 + 7; int inv[N]; int init(){ inv[1] = 1; for(int i = 2; i < N; i ++){ inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD; } } int main(){ init(); }