1. (n!=a*p^k)
将(n!)表示成(a*p^k(a mid p))的形式,其中(p)为已知的素数,求参数(a)和(k)的值
由于在(n!)中能够被(p)整除的数的个数为
[n/p+n/p^2+n/p^3+cdots+n/p^{log _pn}
]
所以可以在(O(log _pn))的时间复杂度内得到(k)的值
对于(a\% p)的计算,由于在(n!)中不能被(p)整除的项在模(p)之后呈周期性(从(1)到((p-1))),所以(n!)中不能被(p)整除的项的积为
[(p-1)!^{(n/p)}*(n\% p)!
]
根据威尔逊定理((p-1)!equiv -1(mod p)),预处理(i!(ileq p)),可以在(O(1))的时间复杂度内得到(n!)中不能被(p)整除的项的积
然后递归处理((n/p)!)中不能被(p)整除的项的积
所以时间复杂度为(O(log _pn))
const int maxp=10010;
int n,p,fac[maxp];
void get_fac(){
fac[0]=1;
for(int i=1;i<p;i++){
fac[i]=fac[i-1]*i%p;
}
}
int mod_fac(int n,int p,int& k){
k=0;
if(n==0) return 1;
int res=mod_fac(n/p,p,k);
k+=n/p;
if((n/p)&1) return res*(p-fac[n%p]%p)%p;
return res*fac[n%p]%p;
}
2. (C_n^m\% p)
(C_n^m=frac{n!}{m!(n-m)!})
设(n!=a_1*p^{k_1},m!=a_2*p^{k_2},(n-m)!=a_3*p^{k_3}),则当(k_1>k_2+k_3)时,(C_n^m)可以被(p)整除,也就是(C_n^mequiv 0(mod p)),当(k_1==k_2+k_3)时,(C_n^m=a_1(a_2*a_3)^{-1})
int mod_comb(int n,int m,int p){
if(n<0 || m<0 || p<0) return 0;
int k1,k2,k3;
int a1=mod_fac(n,p,k1),a2=mod_fac(m,p,k2),a3=mod_fac(n-m,p,k3);
if(k1>k2+k3) return 0;
return a1*inv(a2*a3%p,p)%p;
}