• Codeforces1485F


    题目链接
    参考题解链接
    思路
    最基本的(dp)状态转移方程都能推。
    (dp[i][j]:)到第(i)个数,前缀和为(j)的所有方案数。
    考虑第(a_i)的两种选择方式:
    1、当(a_i=b_i)时,前缀和为(j)时:
    (dp[i][j]=dp[i-1][j-b_i](-inf leq j leq inf)).
    2、当前缀和恰为(b_i)时的所有方案数:
    (dp[i][b[i]]=dp[i-1][j](-inf leq j leq inf)).

    观察第一个式子,可以发现每次相当于把这整个dp左移(b_i)个单位。
    对于第二个式子,那么发现(dp[i][b[i]])所记录的就是(i-1)的所有情况,即是记录过的res。
    代码中的sum其实就可以当作一个基准标,每次向左移动(b[i]),因此对于每次读入的循环先需要(sum-b[i])(mp)记录的是前缀和为(b[i])的所有方案数,因为基准标在向左移动,所以此时的前缀相当于(sum+b[i])(mp[sum+b[i]])就要更新为新的(res),那么新增加的方案数即是(res-mp[sum+b[i]])

    const int N = 2e5 + 10, M = 1e5 + 10;
    const int mod = 1e9 + 7;
    int a[N];
    map<int, int> mp;
    void solve() {
        mp.clear();
        int n;
        scanf("%lld", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
        }
        mp[0] = 1;
        int res = 1;
        LL sum = 0;
        for(int i = 1; i <= n; i++) {
            sum -= a[i];
            LL x = res - mp[sum + a[i]];
            mp[sum + a[i]] = res;
            res = (res + x + mod) % mod;
        }
        printf("%lld
    ", res);
    }
    
  • 相关阅读:
    hdu 1087(LIS变形)
    poj 1088(记忆化搜索)
    hdu 1505(最大子矩阵)
    hdu 1506(好题+DP或者RMQ)
    poj 2593&&poj2479(最大两子段和)
    hdu 1003(最大子段和)
    hdu 2881(LIS变形)
    poj 1692(动态规划)
    CodeForces 626C Block Towers
    CodeForces 626B Cards
  • 原文地址:https://www.cnblogs.com/ZX-GO/p/14482577.html
Copyright © 2020-2023  润新知