標籤:style blog strong io for 2014 amp size
題意:
給一個n個數的數列,從中取一些數構成新數列,
如果新數列中有一些數的和是k,那麼這就是一個好數列,問這樣的數列的個數。
n,k<=20, a[i] <=L
狀態:dp[][state] 中state的二進位每一位表示和為(1~k),1表示可以取到,0表示取不到。
狀態轉移方程:dp[i][state] = sum(dp[i-1][state‘]); state = 1<<(p-1) || state‘ || ((state‘<<p) &SIZE) ; 1<=p<=min(k,L); //SIZE=(1<<k)-1;
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const LL mod = 1e9 + 7;LL dp[1<<22];int main(){ int t, n, k, L; scanf("%d",&t); while(t--) { scanf("%d%d%d", &n, &k, &L); int MIN = min(L, k); int SIZE = (1<<k)-1; memset(dp, 0, sizeof dp ); dp[0] = 1; for(int i=0; i<n; ++i) { for(int j=SIZE; j>=0; --j) if(dp[j]>0) { LL tmp = dp[j]; for(int p=1; p<=MIN; ++p) { int next=(1<<(p-1))|j|((j<<p)&SIZE); //加上p本身這個數 + 原來可取到的數 + 原來可取到的數加上p之後的數,即組成了所有加上p之後的情況 dp[next] =dp[next] + tmp; if(dp[next]>mod) dp[next] -= mod; } if(k<L)//第i個數選大於k的數 { dp[j] = dp[j] + (LL)tmp*(L-k); if(dp[j]>mod) dp[j] -= mod; } } } LL ans = 0; for(int i=0; i<=SIZE; ++i) if(i&(1<<(k-1))) { ans = ans + dp[i]; if(ans>mod) ans -= mod; } printf("%I64d\n", ans); } return 0;}