說明
- 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);
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;
}