[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上海icpc网络赛B. Light bulbs(思维+差分)
01背包方案数(变种题)Stone game--The Preliminary Contest for ICPC Asia Shanghai 2019