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;
}
posted @ 2024-07-15 19:41  SmileMask  阅读(2)  评论(0编辑  收藏  举报