标签:des style blog color os io for div
/* ID: neverchanje PROG: LANG: C++11 */ #include<vector> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<cstdio> #include<set> #include<queue> #include<map> using namespace std; #define INF 1e9 #define maxn #define MOD 1000000007 #define rep(i,x,y) for(int i=x;i<=y;i++) #define mset(x) memset(x,0,sizeof(x)) typedef long long ll; typedef pair<int,int> pii; typedef vector<int> vi; ll dp[1<<(21)] ,t,n,k,l,d, next, maxS; int main(){ // freopen("a.txt","r",stdin); // freopen(".out","w",stdout); cin>>t; while(t--){ cin>>n>>k>>l; mset(dp); d = l>k ? l-k : k-l; l = min(k,l); maxS = (1<<k)-1; dp[0]=1; //dp[0][0]=1; int tmp; rep(i,1,n){ for(int S=maxS; S>=0; S--){ if(dp[S]==0) continue; //重要优化 tmp = dp[S];//必须保存,因为next可能等于S rep(p,1,l){ next = ( S | (1<<(p-1)) | ((S<<p)&maxS) ); dp[ next ] = ( tmp+dp[next] )%MOD; } dp[S] = ( dp[S] + (ll)(tmp*d)%MOD )%MOD; } } ll ans=0; rep(S,0,maxS){ if( S&(1<<(k-1)) ){ ans += dp[S]; ans %= MOD; } } cout<<ans<<endl; } return 0; } /* DESCRIPTION: 枚举n个数的数列a,有ai<=L,如果存在子集使得子集的数之和为k,则a是一个好数列 注意到k<=20 假设a的不同子集和分别是s1,s2,...,st,记做集合S 枚举第i个数p (1 ~ min(l,k)) 每个子集和si+p 会得到新的子集和的集合S‘ dp[i][S+{p}+S‘] += dp[i-1][S]; (S<<p) = S‘ //每个si都加p S+{p}+S‘ = S | (1<<(p-1)) | ((S<<p)&maxS) 边界: dp[0]=1; dp的大小maxS为(1<<k)-1 注意情况: 还要再枚举p (min(l,k) ~ max(l,k)),显然这个p不会被选,但也算作一种情况 dp[i][S] += dp[i-1][S]*(l-k) */
标签:des style blog color os io for div
原文地址:http://www.cnblogs.com/neverchanje/p/3902850.html