题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5800
To My Girlfriend
Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 908 Accepted Submission(s): 348
Problem Description
Dear Guo
I never forget the moment I met with you.You carefully asked me: "I have a very difficult problem. Can you teach me?".I replied with a smile, "of course"."I have n items, their weight was a[i]",you said,"Let's define f(i,j,k,l,m) to be the number of the subset of the weight of n items was m in total and has No.i and No.j items without No.k and No.l items.""And then," I asked.You said:"I want to know
Sincerely yours,
Liao
I never forget the moment I met with you.You carefully asked me: "I have a very difficult problem. Can you teach me?".I replied with a smile, "of course"."I have n items, their weight was a[i]",you said,"Let's define f(i,j,k,l,m) to be the number of the subset of the weight of n items was m in total and has No.i and No.j items without No.k and No.l items.""And then," I asked.You said:"I want to know
∑i=1n∑j=1n∑k=1n∑l=1n∑m=1sf(i,j,k,l,m)(i,j,k,laredifferent)
Sincerely yours,
Liao
Input
The first line of input contains an integer T
(T≤15)
indicating the number of test cases.
Each case contains 2 integers n , s (4≤n≤1000,1≤s≤1000) . The next line contains n numbers: a1,a2,…,an (1≤ai≤1000) .
Each case contains 2 integers n , s (4≤n≤1000,1≤s≤1000) . The next line contains n numbers: a1,a2,…,an (1≤ai≤1000) .
Output
Each case print the only number — the number of her would modulo
109+7
(both Liao and Guo like the number).
Sample Input
2 4 4 1 2 3 4 4 4 1 2 3 4
Sample Output
8 8
Author
UESTC
Source
给n个数,求:
∑i=1n∑j=1n∑k=1n∑l=1n∑m=1sf(i,j,k,l,m)(i,j,k,laredifferent)
i,j为必选数的序号,k,l为必不选数的序号,m是背包体积。
解题思路:
定义dp[i][j][k][l]表示到第i个为止,和正好是j,有k个必选,l个必不选的方法数。
那么分析一下,只有四种情况:选,不选,必选,必不选。
所以dp[i][j][k][l]=dp[i-1][j-a[i]][k][l]+dp[i-1][j][k][l]+dp[i-1][j-a[i]][k-1][l]+dp[i-1][j][k][l-1];
需要注意的是,i和j可以交换,k和l也可以交换,所以最后的结果要乘以4。
详见代码。
//dp[i][j][k][l]表示到第i个为止,和正好是j,有k个必选,l个必不选的方法数
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int Mod=(1e9+7);
#define ll long long
int dp[1010][1010][3][3],a[1010];
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
int n,s;
ll sum=0;
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&s);
for (int i=1; i<=n; i++)
scanf("%d",&a[i]);
dp[0][0][0][0]=1;
for (int i=1; i<=n; i++) //循环每一位数
{
for (int j=0; j<=s; j++) //循环每一个重量
{
for (int k=0; k<=2; k++) //k个必选
{
for (int l=0; l<=2; l++) //l个必不选
{
dp[i][j][k][l]+=dp[i-1][j][k][l];//不选
dp[i][j][k][l]%=Mod;
if (l>0)
{
dp[i][j][k][l]+=dp[i-1][j][k][l-1];//必不选
dp[i][j][k][l]%=Mod;
}
if (j>=a[i])
{
dp[i][j][k][l]+=dp[i-1][j-a[i]][k][l];//选
dp[i][j][k][l]%=Mod;
}
if (k>0&&j>=a[i])
{
dp[i][j][k][l]+=dp[i-1][j-a[i]][k-1][l];//必选
dp[i][j][k][l]%=Mod;
}
}
}
}
}
for (int i=0; i<=s; i++)
{
sum+=dp[n][i][2][2];
sum%=Mod;
}
printf ("%lld\n",(sum*4)%Mod);
}
return 0;
}