zoukankan      html  css  js  c++  java
  • 扩展卢卡斯定理

    解决的问题:
    (C_n^mpmod{p})(p)不是质数。
    (p)分解质数,假设为(p_1^{c_1}*p_2^{c_2}*...*p_k^{c_k})
    对每个(p_i^{c_i})求出在模意义下的(C_n^m),设为(a_i),我们的问题就变为:
    (egin{cases}xequiv a_1pmod{p_1^{c_1}}\ xequiv a_2pmod{p_2^{c_2}}\...\xequiv a_kpmod{p_k^{c_k}}end{cases})
    求这个(x)即为答案,因为模数互质,显然可以用CRT求。

    于是考虑求(C_n^mpmod{p_i^{c_i}})
    发现不能用逆元求(n!),因为不一定存在逆元,(x)存在逆元的条件为(gcd(x,p)=1)

    现在问题就是求(n!)在模(p_i^{c_i})的意义下的逆元,即求(n!)(p_i^{c_i})的值,考虑既然模数只有一个质因子,我们将(n!)中的质因子(p_i)提出,剩下的数必定与(p_i^{c_i})互质,exgcd求逆元即可。

    以下引用自

    (22!mod 3^2)为例:

    按照(3^2)分段:((1*2*3*4*5*6*7*8*9)*(10*11*12*13*14*15*16*17*18)*(19*20*21*22))

    将3提出后为((3^6*(1*2*3*4*5*6*7))*(1*2*4*5*7*8)*(10*11*13*14*16*17)*(19*20*22))

    观察发现前(lfloorfrac{n}{p_i^{c_i}} floor)模意义下相同,求一组时候快速幂即可。((19*20*22))直接暴力算。((1*2*3*4*5*6*7))递归即可。

    提出的(3)因子的数目可以直接算,为(sumlimits_{p^i<=n}lfloorfrac{n}{p^i} floor),证明见lyd蓝书。

    于是求完了。

    模板题

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxp=1000010;
    typedef long long ll;
    ll n,m,mod;
    ll fac[maxp];
    inline ll power(ll x,ll k,ll mod)
    {
    	ll res=1%mod;
    	while(k)
    	{
    		if(k&1)res=res*x%mod;
    		x=x*x%mod;k>>=1;
    	}
    	return res;
    }
    ll calc(ll x,ll p,ll mod)
    {
    	if(x<=1)return 1;
    	ll res=1;
    	if(x>=mod)res=power(fac[mod-1],x/mod,mod);
    	if(x%mod)res=res*fac[x%mod]%mod;
    	return res*calc(x/p,p,mod)%mod;
    }
    void exgcd(ll a,ll b,ll& x,ll& y)
    {
    	if(!b){x=1,y=0;return;}
    	exgcd(b,a%b,x,y);
    	ll z=x;x=y,y=z-(a/b)*y;
    }
    inline ll inv(ll a,ll mod)
    {
    	if(!a)return 0;
    	ll x,y;exgcd(a,mod,x,y);
    	x=(x%mod+mod)%mod;
    	return x;
    }
    inline ll C(ll n,ll m,ll p,ll mod)
    {
    	if(m>n)return 0;
    	fac[0]=1;
    	for(ll i=1;i<mod;i++)fac[i]=fac[i-1]*((i%p)?i:1)%mod;
    	ll a=calc(n,p,mod),b=inv(calc(m,p,mod),mod),c=inv(calc(n-m,p,mod),mod);
    	ll res=a*b%mod*c%mod;
    	int cnt=0;
    	for(ll i=p;i<=n;i*=p)cnt+=n/i;
    	for(ll i=p;i<=m;i*=p)cnt-=m/i;
    	for(ll i=p;i<=n-m;i*=p)cnt-=(n-m)/i;
    	//cerr<<cnt<<endl;
    	return res*power(p,cnt,mod)%mod;
    }
    int main()
    {
    	//freopen("test.in","r",stdin);
    	//freopen("test.out","w",stdout);
    	scanf("%lld%lld%lld",&n,&m,&mod);
    	ll tmp=mod,ans=0;
    	for(ll i=2;i*i<=tmp;i++)
    	{
    		if(tmp%i)continue;
    		ll now=1;
    		while(tmp%i==0)now*=i,tmp/=i;
    		ans=(ans+C(n,m,i,now)*(mod/now)%mod*inv(mod/now,now)%mod)%mod;
    	}
    	if(tmp>1)ans=(ans+C(n,m,tmp,tmp)*(mod/tmp)%mod*inv(mod/tmp,tmp)%mod)%mod;
    	printf("%lld",(ans%mod+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    利用dockerfile定制镜像
    发布Docker 镜像到dockerhub
    Docker 停止容器
    133. Clone Graph
    132. Palindrome Partitioning II
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    127. Word Ladder
  • 原文地址:https://www.cnblogs.com/nofind/p/11929825.html
Copyright © 2011-2022 走看看