$n!=a*p^k$与$C_n^m\% p$

1. \(n!=a*p^k\)

\(n!\)表示成\(a*p^k(a\nmid 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!(i\leq 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^m\equiv 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;
}
posted @ 2020-07-25 23:07  fxq1304  阅读(171)  评论(0编辑  收藏  举报