把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF1485F Copy or Prefix Sum 分析

题目概述

给定一个整数数组 \(b_1, b_2, \ldots, b_n\)

如果一个整数数组 \(a_1, a_2, \ldots, a_n\) 满足对于每个 \(i\)\(1 \leq i \leq n\)),至少满足以下两个条件之一:

  • \(b_i = a_i\),或者
  • \(b_i = \sum_{j=1}^{i} a_j\)

则称该数组为“混合数组”。

请你计算有多少个“混合数组” \(a_1, a_2, \ldots, a_n\)。由于答案可能很大,请输出对 \(10^9 + 7\) 取模后的结果。

数据范围:\(1\leq n\leq 10^5\)

分析

套路地设 \(f_{i,j}\) 表示前 \(i\) 个都填了其和 \(j\) 的方案。

有:

  • \(a_i=b_i\),所以 \(f_{i,j}=f_{i-1,j-b_i}\)
  • \(b_i=\sum a_j\),所以 \(f_{i,b_i}=f_{i-1,x}\),其中 \(x\) 为任意数。

考虑到这样存会炸,而 \(x\) 显然只是和出现过的数相关,直接用 \(map\)

第一个情况相当于位移,第二个情况相当于全局和。

所以考虑维护全局和,第一种情况对全局和不会造成影响,而第二种情况会对全局和贡献上一个的全局和除开上一个本身(应为第二种情况需要覆盖第一种情况)。

直接做就行了。

代码

时间复杂度 \(\mathcal{O}(n\log n)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <map>
#define int long long
// #define N 
using namespace std;
const int mod = 1e9 + 7;
map<int,int> f;
signed main(){
    int T;
    cin >> T;
    for (;T--;) {
        f.clear();
        int n,res = 0,ans;
        ans = f[0] = 1;
        scanf("%lld",&n);
        for (int x;n --;) {
            scanf("%lld",&x);
            int val = ans - f[res];
            f[res] = ans;
            ans = ((ans + val) % mod + mod) % mod;
            res -= x;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2025-11-10 20:20  high_skyy  阅读(10)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end