題目大意
給定陣列 \(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;
}