zoukankan      html  css  js  c++  java
  • 2019-3-15 模拟赛 T1

    题意

    给你一个数 (k)(n) 个桶,有 (m) 个桶有容量上限 (w_i) ,其它桶则没有。求把数拆开放到各个桶里,最终得到序列的方案数。
    数据范围 : (n,k<=5*10^6)(m,w_i<=300)


    做法

    考虑到 (m)(w[i])很小,我们先假装不存在有限制的桶。
    等等!这样不就是插板法裸题了吗?答案显然是(C^{n-1}_{k+n-1})的呀。

    我们再来考虑有限制的情况,因为数据很小,我们考虑把 (k) 分为两份,一份直接暴力dp算出方案数,一份用刚刚的公式计算。枚举分割点(它不会超过 (90000) 个),直接相加即可。

    最后还要注意用前缀和优化dp转移,组合数预处理等。

    做完了,复杂度 (O(n+m^2*w_{max}))


    代码实现

    #include<cstdio>
    const long long mod=1e9+7;
    long long pu[10000005],inv[10000005];
    long long w[305],dp[305][90005],sum[305][90005];
    long long qpow(long long val,long long k){
    	long long ret=1;
    	while(k){
    		if(k&1) ret=ret*val%mod;
    		val=val*val%mod; k>>=1;
    	}
    	return ret;
    }
    long long C(long long n,long long m){
    	return (pu[n]*inv[m]%mod)*inv[n-m]%mod;
    }
    void init(int maxn){
    	pu[0]=1;
    	//!!!!
    	for(int i=1;i<=maxn;i++) pu[i]=pu[i-1]*i%mod;
    	inv[maxn]=qpow(pu[maxn],mod-2);
    	for(int i=maxn-1;i>=0;i--) inv[i]=inv[i+1]*(i+1ll)%mod;
    	dp[0][0]=1;
    	return ;
    }
    int main(){
    	int n,m,k;
    	scanf("%d%d%d",&n,&m,&k);
    	init(n+k);
    	for(int i=1;i<=m;i++) scanf("%lld",&w[i]);
    	int sumw=0;
    	for(int i=1;i<=m;i++){
    		sum[i-1][0]=dp[i-1][0];
    		for(int j=1;j<=sumw;j++)
    			sum[i-1][j]=(sum[i-1][j-1]+dp[i-1][j])%mod;
    		for(int j=sumw+1;j<=sumw+w[i];j++)
    		    sum[i-1][j]=sum[i-1][j-1];
    		sumw+=w[i];
    		dp[i][0]=1;
    		for(int j=1;j<=sumw;j++){
    			if(j<=w[i]) dp[i][j]=(dp[i-1][j]+sum[i-1][j-1])%mod;
    			else dp[i][j]=(dp[i-1][j]+(sum[i-1][j-1]-sum[i-1][j-w[i]-1]+mod)%mod)%mod;
    		}
    	}
    	if(n==m){
    		if(k>=90004)
    			return 0*puts("0");
    		return 0*printf("%lld
    ",dp[n][k]);
    	}
    	long long ans=0;
    	for(int i=0;i<=sumw;i++){
    		if(dp[m][i]==0) continue;
    		ans=(ans+dp[m][i]*C(k-i+(n-m)-1,(n-m)-1)%mod)%mod;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    我的python中级班学习之路(全程笔记第一模块) (第一章)语言基础
    Python_常用模块
    Python_装饰器、迭代器、生成器
    Python_函数
    Python_深浅拷贝
    Python_文件操作
    Python_三级目录
    Python_循环判断表达式
    Python_基础语法
    7段数码管绘制
  • 原文地址:https://www.cnblogs.com/JiuPleber/p/2019_3_15_T1.html
Copyright © 2011-2022 走看看