乘法逆元 模板

fadtes發表於2020-10-14

說明

  • a*x≡1(mod b),且a與b互質,x為a的逆元
  • 對於 a/b(mod p) ,可以求b在mod p 下的逆元,之後 *a(mod p),為原分數的值
  • 常用於大數除法需要取模的情況

擴充套件歐幾里得演算法

  • 擴充套件歐幾里得演算法是求整數x、y 使得 ax+by=1
  • 單點查詢素數快,在a與p互質而p不是質數也可以使用
#include <iostream>
using namespace std;
typedef long long ll;
void Exgcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0)	x=1,y=0;
	else
	{
		Exgcd(b, a%b, y, x);
		y-=a/b*x;
	}
}
int main()
{
	ll x,y,n,p;
	cin>>n>>p;
	for(int i=1;i<=n;i++)
	{
		Exgcd(i,p,x,y);
		x=(x%p+p)%p;
		cout<<x<<endl;
	}
	return 0;
}

快速冪(費馬小定理)

  • 費馬小定理 :若pp為素數,aa為正整數,且aa、pp互質。 則有a(p-1) ≡1(modp)。
  • 代入式子化簡得 x≡ap−2(modp)
#include <iostream>
using namespace std;
typedef long long ll;
ll fpm(ll x,ll power, ll p)
{
	x%=p;
	ll ans=1;
	for(;power;power>>=1)
	{
		if(power&1)
		{
			ans*=x;
			ans%=p;
		}
		x*=x;
		x%=p;
	}
	return ans;
}
int main()
{
	ll n,p;
	cin>>n>>p;
	for(int i=1;i<=n;i++)
	{
		ll x = fpm(i, p-2, p); //x為a在mod p意義下的逆元
		cout<<x<<endl;
	}
	return 0;
 } 

線性演算法

  • 適用於求一連串的逆元
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=4e6+5;
ll inv[maxn];
int main()
{
	ll n,p;
	cin>>n>>p;
	inv[1]=1;
	cout<<inv[1]<<endl;
	for(int i=2;i<=n;i++)
	{
		inv[i]=(p - p / i) * inv[p % i] % p;
		printf("%lld\n",inv[i]);
	}
	return 0;
}