zoukankan      html  css  js  c++  java
  • [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
    ", ans);
    41     }
    42 }

  • 相关阅读:
    我叫mt3.0更新公告
    gcc 编译器常用的命令行参数一览
    C++两个类相互引用错误留影
    C++中的声明与定义
    C++ 杂记
    C++中两个类相互包含引用的相关问题
    Ogre 中使用OIS的两种模式
    Ogre 渲染队列(二)
    Ogre 渲染队列(一)
    Ogre 场景管理器
  • 原文地址:https://www.cnblogs.com/sainsist/p/11524215.html
Copyright © 2011-2022 走看看