codeforces1485 F. Copy or Prefix Sum(dp)
F. Copy or Prefix Sum
Venice technique簡要就是懶標(biāo)記思想。
由于前綴和數(shù)組和原數(shù)組一一對應(yīng),這里我們選擇求aia_iai?的前綴和數(shù)組的方案數(shù)(下面aia_iai?表示原題數(shù)組的前綴和)
不難得知原題目的兩個條件即
- bi=ai?ai?1→ai=bi+ai?1b_i=a_i-a_{i-1} \to a_i=b_i+a_{i-1}bi?=ai??ai?1?→ai?=bi?+ai?1?
- bi=ai→ai=bib_i=a_i \to a_i=b_ibi?=ai?→ai?=bi?
狀態(tài)表示:fi,jf_{i,j}fi,j?考慮前iii個數(shù),所求數(shù)組第iii個位置值是jjj的方案數(shù)。
答案即是:∑j=?∞+∞fn,j\sum_{j=-\infty}^{+\infty}f_{n,j}∑j=?∞+∞?fn,j?
狀態(tài)轉(zhuǎn)移:
- fi,j=fi?1,j?bif_{i,j}=f_{i-1,j-b_i}fi,j?=fi?1,j?bi??
- fi,bi=∑j=?∞+∞fi?1,j?(fi?1,0)f_{i,b_i}=\sum_{j=-\infty}^{+\infty}f_{i-1,j}-(f_{i-1,0})fi,bi??=∑j=?∞+∞?fi?1,j??(fi?1,0?)
ai=bi+ai?1a_i=b_i+a_{i-1}ai?=bi?+ai?1?和ai=bia_i=b_iai?=bi?當(dāng)ai?1=0a_{i-1}=0ai?1?=0時是同一種情況,因此需要把重復(fù)計算的去掉。
按照上述轉(zhuǎn)移方式肯定不可信,不難發(fā)現(xiàn)第一維可以用滾動數(shù)組優(yōu)化掉,注意第一個轉(zhuǎn)移式子,相當(dāng)于將整個數(shù)組平移bib_ibi?,這里采用的懶標(biāo)記的思想做一個下標(biāo)映射。
對于第一種轉(zhuǎn)移,維護(hù)一個add,fi,j=fi?1,j?bi=fi?1,j+addf_{i,j}=f_{i-1,j-b_i}=f_{i-1,j+add}fi,j?=fi?1,j?bi??=fi?1,j+add?,如果每次讓add減去bib_ibi?就完成了對數(shù)組的平移操作也就是第一種轉(zhuǎn)移。
而下面一種轉(zhuǎn)移,只需要記住原來bib_ibi?的位置是bi+addb_i+addbi?+add即可轉(zhuǎn)移
#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr) #pragma GCC optimize(2) #include<map> #include<iostream> #include<algorithm> using namespace std; using ll=long long; constexpr int N=100010; constexpr ll mod=1e9+7; int n; map<ll,ll> dp; int main() {IO;int T=1;cin>>T;while(T--){cin>>n;dp.clear();dp[0]=1;ll sum=1,add=0;for(int i=1;i<=n;i++){ll b;cin>>b;ll pre=sum-dp[0+add]; pre=(pre%mod+mod)%mod;add-=b;sum+=pre; sum%=mod;dp[b+add]+=pre; dp[b+add]%=mod;}cout<<sum<<'\n';}return 0; } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的codeforces1485 F. Copy or Prefix Sum(dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于电脑升级的CPU知识电脑CPU升级
- 下一篇: 不担心电脑C盘空间不足了电脑C盘空间不足