zoukankan      html  css  js  c++  java
  • hihocoder offer收割编程练习赛8 C 数组分拆

    思路:(引自bfsoyc的回答:http://hihocoder.com/discuss/question/4160

    动态规划。状态dp[i]表示 前i个数的合法的方案数,转移是

    dp[i] = sum{ dp[k] | 1 < k < i && sum(k+1,i)!=0 }

            = sum{ dp[k] | 1 < k < i } - sum{ dp[k] | 1 < k < i && sum(k+1,i)==0 }

    关键是求后半部分怎么找到sum(k+1,i)==0 的k, 等价于找 prefixSum(k)== prefixSum(i),因为这里前缀比后缀维护容易。利用容器map M, M[ps] = sum{dp[k] | prefixSum(k)==ps }。 那么 dp[i] = sum{ dp[k] | 1 < k < i } - M[prefixSum(i)]。

    实现:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <map>
     4 using namespace std;
     5 
     6 const int mod = 1e9 + 7;
     7 int a[100005], s[100005], dp[100005], n, total;
     8 map<int, int> g;
     9 
    10 int solve()
    11 {
    12     total = dp[0] = 1;
    13     g[0] = 1;
    14     for (int i = 1; i <= n; i++)
    15     {
    16         if (!g.count(s[i]))
    17             g[s[i]] = 0;
    18         dp[i] = ((total - g[s[i]]) % mod + mod) % mod;
    19         g[s[i]] = (g[s[i]] + dp[i]) % mod;
    20         total = (total + dp[i]) % mod;
    21     }
    22     return dp[n];
    23 }
    24 
    25 int main()
    26 {
    27     cin >> n;
    28     for (int i = 1; i <= n; i++)
    29     {
    30         scanf("%d", &a[i]);
    31         s[i] = s[i - 1] + a[i];
    32     }
    33     cout << solve() << endl;
    34     return 0;
    35 }
  • 相关阅读:
    memcached构建集群分析之一
    linux使用getopt解析参数
    setbuffer和freopen做一个简单的日志组件
    setbuf和freopen
    编码规范的重要性
    c++的操作符格式记录
    do{...}while(0)的作用
    CF div2 321 C
    CF div2 321 B
    CF div2 321 A
  • 原文地址:https://www.cnblogs.com/wangyiming/p/6542660.html
Copyright © 2011-2022 走看看