标签:
题意:给出一个序列(1000长度),定义f(i,j,k,l,m) 为a[i],a[j]必取,a[k],a[l]必不取和为m的子集个数。统计任一i,j,k,l,m的和是多少(i!=j!=k!=l)
dp[i][j][k][l],表示前i个组成重量j,有k个必取l个必不取的方案数,当i+1则分四种情况,a[i+1]为必取,非必取,既不为必取也不为非必取讨论
#include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <algorithm> #include <queue> #include <map> using namespace std; typedef long long ll; const int N = 1000+10; const int mod=1e9+7; const double en=2.718281828459; using namespace std; int t,n,s,a[N]; int dp[N][N][3][3]; int main() { //freopen("in.txt","r",stdin); cin>>t; while(t--){ scanf("%d%d",&n,&s); memset(dp,0,sizeof(dp)); int i,j,s1,s2; for(i=1;i<=n;i++) scanf("%d",&a[i]); dp[0][0][0][0]=1; for(i=1;i<=n;i++) for(j=0;j<=s;j++) for(s1=0;s1<=2;s1++) for(s2=0;s2<=2;s2++){ dp[i][j][s1][s2]+=dp[i-1][j][s1][s2]; dp[i][j][s1][s2]%=mod; if(j>=a[i]){ dp[i][j][s1][s2]+=dp[i-1][j-a[i]][s1][s2]; dp[i][j][s1][s2]%=mod; } if(s2>=1){ dp[i][j][s1][s2]+=dp[i-1][j][s1][s2-1]; dp[i][j][s1][s2]%=mod; } if(j>=a[i]&&s1>=1){ dp[i][j][s1][s2]+=dp[i-1][j-a[i]][s1-1][s2]; dp[i][j][s1][s2]%=mod; } } ll sum=0; for(int i=1;i<=s;i++){ sum+=dp[n][i][2][2]; sum%=mod; } cout<<(sum*4)%mod<<endl; } }
标签:
原文地址:http://www.cnblogs.com/shimu/p/5743994.html