除法取模
trivial
当时,有
证明:
设
则
所以
证毕。
untrivial
方程的解称为
关于模
的逆元,记为
。当
时,方程有唯一解,否则无解。
于是可以转化为
来计算。
显然,,
费马小定理
定理:若是质数,且
,则
。
此时,即
关于
的逆元为
。
快速幂
ll qPow(ll a,ll n,ll p)
{
if (a==0) {
return 0;
}
ll ans=1;
a%=p;
while (n) {
if (n&1) {
ans=ans*a%p;
}
a=a*a%p;
n>>=1;
}
return ans;
}
扩展欧几里德算法
组合数取模
递推
Lucas定理
定理:若为质数,对任意整数
,有
另一种形式:若为质数,对任意整数
,有
其中和
分别表示
和
在
进制下第
位的值。
模板题-HDOJ3057
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int MAXN=(int)1e5+10;
ll fac[MAXN];
void init(int p);
ll Lucas(ll n,ll m,ll p);
ll comb(ll n,ll m,ll p);
ll inv(ll a,ll p);
ll qPow(ll a,ll n,ll p);
int main()
{
int T;
cin>>T;
while (T--) {
int n,m,p;
cin>>n>>m>>p;
init(p);
cout<<Lucas(n+m,m,p)<<endl;
}
return 0;
}
void init(int p)
{
fac[0]=1;
for (int i=1;i<p;i++) {
fac[i]=fac[i-1]*i%p;
}
}
ll Lucas(ll n,ll m,ll p)
{
ll ans=1;
while (n && m && ans) {
ans=ans*comb(n%p,m%p,p)%p;
n/=p;
m/=p;
}
return ans;
}
ll comb(ll n,ll m,ll p)
{
if (n<m) {
return 0;
};
ll ans=fac[n]*inv(fac[m],p)%p*inv(fac[n-m],p)%p;
return ans;
}
ll inv(ll a,ll p)
{
return qPow(a,p-2,p);
}
ll qPow(ll a,ll n,ll p)
{
if (a==0) {
return 0;
}
ll ans=1;
a%=p;
while (n) {
if (n&1) {
ans=ans*a%p;
}
a=a*a%p;
n>>=1;
}
return ans;
}