• bzoj 2142: 礼物


    Description

    一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E
    心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。小E从商店中购买了n件礼物,打算送给m个人
    ,其中送给第i个人礼物数量为wi。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某
    个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。

    Solution

    答案就是 (Pi_{i=1}^{n} C_{n-sum_{j=1}^{i-1}w_j}^{w_i})
    (exlucas) 求一下就行了,一些细节写在代码里了

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int Fac[N];ll P,w[10];
    inline ll ksc(ll x,ll k,ll mod){
    	ll sum=0;k=(k%mod+mod)%mod;
    	while(k){
    		if(k&1)sum=(sum+x)%mod;
    		x=(x+x)%mod;k>>=1;
    	}
    	return sum;
    }
    inline int qm(int x,int k,int mod){
    	int sum=1;
    	while(k){
    		if(k&1)sum=1ll*sum*x%mod;
    		x=1ll*x*x%mod;k>>=1;
    	}
    	return sum;
    }
    inline void exgcd(ll a,ll b,ll &x,ll &y){
    	if(!b)x=1,y=0;
    	else exgcd(b,a%b,y,x),y-=a/b*x;
    }
    inline ll inv(ll a,ll b){
    	ll x,y;exgcd(a,b,x,y);
    	return (x%b+b)%b;
    }
    inline int fac(int n,int p,int pr){
    	if(n<=1)return 1;
    	int ret=Fac[pr];
    	ret=qm(ret,n/pr,pr);
    	ret=1ll*ret*Fac[n%pr]%pr;
    	return 1ll*ret*fac(n/p,p,pr)%pr; 
    }
    inline ll C(int n,int m,int p,int pr){
    	int c=0;
    	for(ll i=p;i<=n;i*=p)c+=n/i;  //long long !!
    	for(ll i=p;i<=m;i*=p)c-=m/i;
    	for(ll i=p;i<=n-m;i*=p)c-=(n-m)/i;
    	int a=fac(n,p,pr),b=fac(m,p,pr),d=fac(n-m,p,pr);
    	int ret=1ll*a*inv(b,pr)%pr*inv(d,pr)%pr*qm(p,c,pr)%pr;
    	return ksc(ksc((P/pr),inv(P/pr,pr),P),ret,P);  //!!
    }
    inline ll exlucas(int n,int m){
    	if(n<m)return 0;
    	ll ret=0,x=P;
    	for(int i=2;i<=100000;i++)if(x%i==0){
    			int p=1;
    			while(x%i==0)p*=i,x/=i;
    			Fac[0]=1;
    			for(int j=1;j<=p;j++)Fac[j]=1ll*Fac[j-1]*(j%i?j:1)%p;
    			ret=(ret+C(n,m,i,p))%P;
    		}
    	if(x>1){
    		Fac[0]=1;
    		for(int j=1;j<=x;j++)Fac[j]=1ll*Fac[j-1]*(j%x?j:1)%x;
    		ret=(ret+C(n,m,x,x))%P;
    	}
    	return ret;
    }
    int main(){
    	freopen("pp.in","r",stdin);
    	freopen("pp.out","w",stdout);
    	int n,m;ll ans=1,sum=0;
    	cin>>P>>n>>m;
    	for(int i=1;i<=m;i++)cin>>w[i],sum+=w[i];
    	if(sum>n)puts("Impossible"),exit(0);
    	for(int i=1;i<=m;i++){
    		ans=ksc(ans,exlucas(n,w[i]),P);
    		n-=w[i];
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    网站设计十忌
    sql优化代码
    负载均衡技术 (4)
    负载均衡技术 (3)
    使用exe4j打包jar生成exe常用设置
    大型网站设计注意事项
    大型企业网站建设存在的十大问题分析
    电子商务网站必须要解决的若干技术问题
    电子商务系统的商品实体分析和设计
    JFfreeChart使用文档
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8721233.html
Copyright © 2020-2023  润新知