[2019上海网络赛J题]Stone game

Posted sainsist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[2019上海网络赛J题]Stone game相关的知识,希望对你有一定的参考价值。

题目链接 CSLnb!

题意是求出给定集合中有多少个合法子集,合法子集的定义为,子集和>=总和-子集和&&子集和-(子集的子集和)<=总和-子集和。

其实就是很简单的dp,先将集合从大到小排序,dp[i][j]表示以a[i]为子集的最小值时,子集和为j的方案数。因为排序后保证遍历到的a[i]一定为当前最小值,所以暴力统计转移即可。

最后在统计一遍合法答案。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod = 1e9 + 7;
 5 int a[310];
 6 int dp[305][150010];
 7 int sm[150010];
 8 int add(int a, int b) 
 9     a += b;
10     if (a >= mod)
11         a -= mod;
12     return a;
13 
14 int main() 
15     int t;
16     scanf("%d", &t);
17     while (t--) 
18         int n, sum = 0;
19         scanf("%d", &n);
20         for (int i = 1; i <= n; i++)
21             scanf("%d", &a[i]), sum += a[i];
22         sort(a + 1, a + 1 + n, greater<int>());
23         dp[0][0] = 1;
24         sm[0] = 1;
25         for (int i = 1; i <= n; i++) 
26             for (int j = sum; j >= a[i]; j--) 
27                 dp[i][j] = sm[j - a[i]];
28                 sm[j] = add(sm[j], dp[i][j]);
29             
30         
31         int ans = 0;
32         for (int i = 1; i <= n; i++) 
33             for (int j = 0; j <= sum; j++) 
34                 if (j >= sum - j && j - a[i] <= sum - j)
35                     ans = add(ans, dp[i][j]);
36                 dp[i][j] = 0;
37                 sm[j] = 0;
38             
39         
40         printf("%d\n", ans);
41     
42 

 

以上是关于[2019上海网络赛J题]Stone game的主要内容,如果未能解决你的问题,请参考以下文章

2019上海网络赛

2019上海赛区网络赛(C,G)

2019上海icpc网络赛B. Light bulbs(思维+差分)

01背包方案数(变种题)Stone game--The Preliminary Contest for ICPC Asia Shanghai 2019

2017乌鲁木齐网络赛 J题 Our Journey of Dalian Ends ( 最小费用最大流 )

2019徐州网络赛