类型0:n,m<=1000 直接暴力预处理杨辉三角,预处理复杂度O(n*n) 公式:C(n,m)=C(n,n-m)=C(n-1,m-1)+C(n-1,m)
类型1:n,m<=1e6 且模数p是质数。 O(n)预处理 阶乘fac[i]和阶乘的逆ifac即可。然后 C(n,m)=fac[n]*ifac[m]*ifac[n-m]
预处理复杂度O(n),查询O(1)。HDU6333 Problem B. Harvest of Apples 莫队算法+逆元
类型2:n,m <=1e9 且模数p为质数,且p<=1e5,用Lucas定理,展开成多个组合数的乘积。
单次查询复杂度O(p*log(n)/log(p)) HDU3037 Saving Beans Lucas 定理+逆元
类型3:n<=1e9,m<=1e5, p<=1e9且为质数,用逆元暴力计算C(n,m)=n*(n-1)*(n-2)*……*(n-m+1)/(1*2*……*m)
算法复杂度O(m)
类型4: n,m<=1e5,mod非质数, 对阶乘分解质因数,然后跑快速幂,算法复杂度O(n)
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+1;
const long long MOD=1e9+7;
int prim[MAX],fac[MAX];
void prime()
{
memset(prim,0,sizeof(prim));
for(int i=2;i<MAX;i++)
{
if(!prim[i]) prim[++prim[0]]=i;
for(int j=1;j<=prim[0]&&prim[j]<=MAX/i;j++)
{
prim[prim[j]*i]=1;
if(i%prim[j]==0) break;
}
}
}
void factor(int a,int b)
{
memset(fac,0,sizeof(fac));int i;
for(i=1;i<=prim[0]&&prim[i]<=a;i++)
{
int tmp=a;
while(tmp)
{
fac[i]+=tmp/prim[i];
tmp/=prim[i];
}
}
fac[0]=i;
for(i=1;i<=prim[0]&&prim[i]<=b;i++)
{
int tmp=b;
while(tmp)
{
fac[i]-=tmp/prim[i];
tmp/=prim[i];
}
}
for(i=1;i<=prim[0]&&prim[i]<=a-b;i++)
{
int tmp=a-b;
while(tmp)
{
fac[i]-=tmp/prim[i];
tmp/=prim[i];
}
}
}
long long pow(long long a,int k,long long mod)//快速幂取模
{
long long b=1;
while(k)
{
if(k&1) b=b*a%mod;
a=a*a%mod;
k>>=1;
}
return b;
}
long long C(int a,int b)
{
factor(a,b);
long long c=1;
for(int i=1;i<fac[0];i++) if(fac[i]) c=c*pow(prim[i],fac[i],MOD)%MOD;
return c;
}
int main()
{
int n,m;
prime();
while(~scanf("%d%d",&n,&m))
printf("%I64d\n",C(n,m));
return 0;
}
附 大数质因分解
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+1;
int prim[MAX],fac[MAX][2],facnt;
void prime()
{
memset(prim,0,sizeof(prim));
for(int i=2;i<MAX;i++)
{
if(!prim[i]) prim[++prim[0]]=i;
for(int j=1;j<=prim[0]&&prim[j]<=MAX/i;j++)
{
prim[prim[j]*i]=1;
if(i%prim[j]==0) break;
}
}
}
int factor(long long x)
{
memset(fac,0,sizeof(fac));facnt=0;
long long tmp=x;
for(int i=1;prim[i]<=tmp/prim[i];i++)
{
fac[facnt][1]=0;
if(tmp%prim[i]==0)
{
fac[facnt][0]=prim[i];
while(tmp%prim[i]==0)
{
fac[facnt][1]++;
tmp/=prim[i];
}
facnt++;
}
}
if(tmp!=1)
{
fac[facnt][0]=tmp;
fac[facnt++][1]=1;
}
return facnt;
}
int main()
{
prime();
factor(1024*1000);
printf("");
return 0;
}
类型5:
类型6: 中国剩余定理+lucas