Codeforces 1485F Copy or Prefix Sum
题目链接
题目大意
给定一个长度为 \(N\) 的序列 \(bi\)
问有多少个长度为 \(N\) 的序列 \(a\) 使得
- \(b[i] = a[i]\)
或
- \(b[i] = ∑a[j] , j∈[1,i]\)
解题思路
定义 $dp[i][j] $ 表示前 \(i\) 项的前缀和为 \(j\) 的序列 \(a\) 的个数,其中 \(dp[0][0] = 1\)
( 因为前缀和很大,所以需要用 \(map\) 来操作 )
那么:
当 \(b[i] = a[i]\) 时 , \(dp[i][j] = dp[i - 1][j - b[i]]\)
当 \(b[i] = ∑a[j] , j∈[1,i]\) 时 , \(dp[i][b[i]] = ∑dp[i - 1][j],j∈[-inf,inf]\)
对于第一种转移相当于把整个数组的值向右平移 \(b[i]\)
对于第二种转移需要注意当 \(sum[i-1] = 0\) 时,\(b[i]\) 既等于 \(a[i]\) 又等于 \(∑a[j] , j∈[1,i]\)
相当于多转移了一次 \(dp[i - 1][0]\) ,所以需要减去 \(dp[i - 1][0]\)
最后的答案 \(ans = ∑dp
[j],j∈[-inf,inf]\) ,复杂度为 \(N^2logN\) ( \(log\) 的复杂度源于 \(map\) )考虑优化:
定义 \(sum[i]\) 表示长度为 \(i\) 且满足题目条件的序列 \(a\) 的个数
对于第一种转移,只是把数值向右平移,并不会导致答案的个数增加,所以 \(sum[i] = sum[i - 1]\)
对于第二种转移,\(dp[i][b[i]] += sum[i - 1]\) , 同时减去 \(dp[i - 1][0]\) ,相当于 \(sum[i] += sum[i - 1] , sum[i] -= dp[i - 1][0]\)
于是我们可以定义 \(py\) 表示平移的长度,起初 \(py = 0\),每计算完 \(sum[i]\) 后 , 令 \(py += b[i]\)
那么 \(dp[i - 1][j]\) 则可以用 \(dp[j - py]\) 表示
而 \(dp[i][j]\) 则可以用 \(dp[j - py - b[i]]\) 表示
于是可得 \(sum[i] += sum[i - 1] - dp[0 - py]\) , \(dp[b[i] - py - b[i]] += sum[i - ] - dp[0 - py]\)
最后的答案 \(ans = sum
\) , 复杂度为 \(NlogN\)
AC_Code
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 3e5 + 10 , mod = 1e9 + 7; map<int , int>dp; int b ; signed main() { int T = 1; cin >> T; while(T --) { dp.clear(); int n , sum = 1 , py = 0; cin >> n; for(int i = 1 ; i <= n ; i ++) cin >> b[i]; dp[0] = 1; for(int i = 1 ; i <= n ; i ++) { int add = (sum - dp[0 - py] + mod) % mod; sum = (sum + add) % mod , py += b[i]; dp[b[i] - py] = (dp[b[i] - py] + add) % mod; } cout << sum << '\n'; } return 0; }
- codeforces 85D D. Sum of Medians Vector的妙用
- Codeforces 85 D. Sum of Medians
- codeforces 616E - Sum of Remainders
- codeforces 285 D Permutation Sum (状态压缩DP)
- CodeForces - 910C Minimum Sum(贪心)
- Codeforces 276C Little Girl and Maximum Sum【贪心】
- Codeforces——大数组求sum超时、神级算法__
- 【Codeforces 276C】Little Girl and Maximum Sum
- 【codeforces 703 D】【离线询问 树状数组 前驱思想 前缀异或和】D. Mishka and Interesting sum【 区间内出现次数偶数的数的异或和】
- codeforces - Tricky Sum(模拟)
- CodeForces 396 B.On Sum of Fractions(数论)
- Codeforces 847 C. Sum of Nestings (技巧)
- Codeforces 616E - Sum of Remainders
- Codeforces 895A (入门 prefix sum)
- 【CodeForces】598A - Tricky Sum(计数)
- Codeforces 914G Sum the Fibonacci
- CodeForces 608 B. Hamming Distance Sum(水~)
- Codeforces-489C-Given Length and Sum of Digits...
- Codeforces 276C Little Girl and Maximum Sum(线段树的区间更新)
- Codeforces 703D Mishka and Interesting sum 树状数组