CodeForces - 1485F
题目大意
给定数组 \(b\),求有多少 \(a\) 数组满足 \(a_i=b_i \ or\ \sum\limits_{k=1}^i a_k=b_i\)。
分析
既然有前缀和,不妨将前缀和计入状态中,设 \(dp_{i,j}\) 为前 \(i\) 个前缀和为 \(j\) 的方案数。
考虑两种条件的转移方程。
- 若选第一种,有 \(dp_{i,j}=dp_{i-1,j-b_i}\)
- 若选第二种,有 \(dp_{i,b_i}=\sum\limits_{k=-\infty}^{+\infty} dp_{i-1,k}\)
此处 \(dp_{i,b_i}\) 会多算一次 \(dp_{i-1,0}\),需要减去。
直接实现这个 \(dp\) 显然不现实,挖掘其中性质,发现第一种条件即为将原本的数列平移,第二种也只是单点赋值。
由上,考虑记录一个 \(pos\) 为数组偏移度,一个 \(tot\) 为总方案数。
那么显然 \(dp_{i,b_i}\) 即为 \(tot\),每次动态更新 \(tot\) 即可
代码
map <int,int> f;
void Main(){
f.clear();
f[0]=tot=1;
n=rd,pos=0;
for(int i=1;i<=n;i++){
b=rd,pos+=b;
int x=(tot-f[b-pos]+mod)%mod;
f[b-pos]=tot;
tot=(tot+x)%mod;
}
cout<<tot<<endl;
}