乘法逆元

乘法逆元

若整数\(b,p\)互质,并且\(b|a\),则存在一个整数\(x\)使得\(a/b≡a*x(mod p)\) ,则称\(x\)\(b\) mod \(p\)的乘法逆元

记为\(b-1\)(mod \(p\)

我们先来看看有什么用

当输出结果很大时,要模一个mod再输出

\((a+b)\%mod=a\%mod+b\%mod\)

\((a-b)\%mod=a\%mod-b\%mod\)

\((a*b)\%mod=a\%mod*b\%mod\)

\((a/b)\%mod\)

乘法逆元派上用场了,设\(b\)\(p\)的乘法逆元为\(inv\)

\((a/b)\%p=(a*inv)\%p=a\%p*inv\%p\)

为什么呢? 因为\(b*inv≡1(mod p)\)

\(a/b*b*inv=a*inv≡ a/b(mod p)\)
举个例子 要求(110/10)%7

\(11x≡1 (mod 7) x=9\)

\((110/10)\%7=(110\%7)*(9\%7)=5*2\%7=3\)

接下来是三种代码实现

1扩展欧几里得(exgcd) O(nlogn)

\(ax!≡1\)(mod \(p\)) 设\(ax=yp+1,b=-p\)\(ax+by=1\)

void exgcd(int a,int b)
{
    if(b==0) g=a,x=1,y=0;
    else{
        exgcd(b,a%b);
        int x1=y,y1=x-a/b*y;
        x=x1,y=y1;
        printf("%d*(%d)+%d*(%d)=%d\n",a,x,b,y,g);
    }
}
inv[a]=(x+p)%p;

2费马小定理O(nlogn)

复杂度 欧拉函数\(O(n)\),快速幂\(O(logn)\)

假如\(p\)是质数,且\(gcd(a,p)=1\),那么 \(a^{p-1}≡1\)(mod \(p\))

由费马小定理 \(a^{p-1} ≡1\)$ , 变形得$$aa^{p-2}≡1\((mod p),答案已经很明显了:若\)a,p\(互质,因为且\)aa^{p-2}≡1$$(mod p)且a*x≡1(mod p)\(,则\)x=a^{p-2}$,用快速幂可快速求之.

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int N=3e6+5;
inline int read() {
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x;
}
typedef long long LL;
int n,p;
inline LL qpow(LL a,LL b) {
	LL ans=1;
	while(b) {
		if(b&1) ans=ans*a%p;
		a=a*a%p;
		b>>=1;
	}
	return ans;
}
int main() {
	n=read();p=read();
	for(int i=1;i<=n;+i++)
		printf("%d\n",qpow(i,p-2));
	return 0;
}

3欧拉定理O(nlogn)

定理内容:如果\(a,p\)互质,那么\(a^φ(p) ≡ 1\),当 p 为质数时,\(φ(p)=p-1\)

  同理,结合同余方程,得 \(x=a^{p-2}\)(mod p),用快速幂可快速求之即可

代码同上

4线性递推 O(n)

#include<bits/stdc++.h>
using namespace std;
#define N 3000010
typedef long long ll;
int n,p;
ll inv[N];
int main(){
    scanf("%d%d",&n,&p);
    puts("1");
    inv[1]=1;
    for(int i=2;i<=n;i++) {
        inv[i]=(ll)p-(p/i)*inv[p%i]%p;
        printf("%lld\n",inv[i]);
    }
    return 0;
}

lg T118233 一本通(蓝)P400

posted @ 2020-09-18 16:47  ke_xin  阅读(30)  评论(0编辑  收藏  举报