To My Girlfriend
Total Submission(s): 157 Accepted Submission(s): 49
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
Input
The first line of input contains an integer
T
indicating the number of test cases.
Each case contains
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
2016 Multi-University Training Contest 6
题目大意:
n个数。对于s,查询
∑ni=1∑nj=1∑nk=1∑nl=1∑sm=1f(i,j,k,l,m)(i,j,k,laredifferent)
f(i,j,k,l,m)
表示集合中必须含有
ai
和
aj
,必须没有
ak
和
al
,和为m的集合个数。
直接上DP数组定义:
dp[i][j][k][l]
表示对于前i个数,能选择出的和为j,一定含有k个元素,一定不含l个元素,的集合个数。
O(ns2^3)四层循环跑一下就行了。具体转移方程写完for里面就好推了。
赛后交MLE了一发。居然忘了滚动数组优化了。罪过啊~~~
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread(ch) freopen(ch,"r",stdin)
#define fwrite(ch) freopen(ch,"w",stdout)
using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const int mod = 1e9+7;
const double eps = 1e-8;
int dp[2][1001][3][3];
int main()
{
//fread("");
//fwrite("");
int t,n,s;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&s);
int x;
memset(dp[0],0,sizeof(dp[0]));
dp[0][0][0][0] = 1;
int pos = 1;
for(int i = 1; i <= n; ++i)
{
scanf("%d",&x);
memset(dp[pos],0,sizeof(dp[pos]));
for(int j = 0; j <= s; ++j)
{
for(int k = 0; k <= 2; ++k)
{
for(int r = 0; r <= 2; ++r)
{
//集合不包含当前元素,也不把当前元素作为不可选
dp[pos][j][k][r] = (dp[pos][j][k][r]+dp[pos^1][j][k][r])%mod;
//集合不包含当前元素,把当前元素作为不可选
if(r) dp[pos][j][k][r] = (dp[pos][j][k][r]+dp[pos^1][j][k][r-1])%mod;
if(j+x > s) continue;
//集合包含当前元素,也不把当前元素作为必选
dp[pos][j+x][k][r] = dp[pos^1][j][k][r];
//集合包含当前元素,把当前元素作为必选
if(k) dp[pos][j+x][k][r] = (dp[pos][j+x][k][r]+dp[pos^1][j][k-1][r])%mod;
}
}
}
pos ^= 1;
}
pos ^= 1;
LL ans = 0;
for(int i = 1; i <= s; ++i)
{
ans = (ans+dp[pos][i][2][2])%mod;
}
printf("%lld\n",(ans*4)%mod);
}
return 0;
}