zoukankan      html  css  js  c++  java
  • [HDU4906]Our happy ending

    [HDU4906]Our happy ending

    题目大意:

    让你构造一个(n(nle20))个数的数列,其中每个数都为小于等于(l(lle10^9))的非负整数。

    问你能构造出多少个这样的数列,使其其中几个数相加和为(k(kle20))

    思路:

    状压DP。

    (f[i][j])表示有(i)个数在(0sim min(k,l))范围内,可以构成的和的集合为(j)的时,这(i)个数取值的方案数。

    计算答案时乘以(i)是哪些位置的组合数,以及剩下(n-i)个位置填什么的方案数即可。

    时间复杂度(mathcal O(2^nn(log(n)+k)))

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    typedef long long int64;
    const int N=21,K=21,mod=1e9+7;
    int f[2][1<<K],fac[N],ifac[N];
    void exgcd(const int &a,const int &b,int &x,int &y) {
    	if(!b) {
    		x=1,y=0;
    		return;
    	}
    	exgcd(b,a%b,y,x);
    	y-=a/b*x;
    }
    inline int inv(const int &x) {
    	int ret,tmp;
    	exgcd(x,mod,ret,tmp);
    	return (ret%mod+mod)%mod;
    }
    inline int C(const int &n,const int &m) {
    	return (int64)fac[n]*ifac[m]%mod*ifac[n-m]%mod;
    }
    inline int power(int a,int k) {
    	int ret=1;
    	for(;k;k>>=1) {
    		if(k&1) ret=(int64)ret*a%mod;
    		a=(int64)a*a%mod;
    	}
    	return ret;
    }
    int main() {
    	for(register int T=getint();T;T--) {
    		const int n=getint(),k=getint(),l=getint();
    		for(register int i=fac[0]=1;i<=n;i++) {
    			fac[i]=(int64)fac[i-1]*i%mod;
    		}
    		ifac[n]=inv(fac[n]);
    		for(register int i=n;i>=1;i--) {
    			ifac[i-1]=(int64)ifac[i]*i%mod;
    		}
    		const int all=(1<<(k+1))-1;
    		memset(f[0],0,sizeof f[0]);
    		f[0][1]=1;
    		int ans=0;
    		for(register int i=0;i<n;i++) {
    			const bool cur=i&1;
    			memset(f[!cur],0,sizeof f[!cur]);
    			for(register int j=0;j<=all;j++) {
    				if(f[cur][j]==0) continue;
    				for(register int m=0;m<=std::min(l,k);m++) {
    					(f[!cur][j|((j&(all>>m))<<m)]+=f[cur][j])%=mod;
    				}
    				if((j>>k)&1) {
    					(ans+=(int64)f[cur][j]*power(std::max(l-k,0),n-i)%mod*C(n,i)%mod)%=mod;
    				}
    			}
    		}
    		for(register int j=0;j<=all;j++) {
    			if((j>>k)&1) (ans+=f[n&1][j])%=mod;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    boost 无锁队列
    boost::asio 的同、异步方式
    MFC获取当前时间
    利用boost获取时间并格式化
    VS2008找不到MFC90d.dll错误解决方法
    boost库在工作(39)网络UDP异步服务端之九
    boost::asio译文
    windows 和linux 同步api对比
    BOOST::Signals2
    redhat 各种版本下载
  • 原文地址:https://www.cnblogs.com/skylee03/p/9752487.html
Copyright © 2011-2022 走看看