--- title: Codeforce 1000 D. Yet Another Problem On a Subsequence 解析(DP) description: "Codeforce 1000 D. Yet Another Problem On a Subsequence 解析(DP)" disqus: hackmd --- <meta name="robots" content="Codeforce 1000 D. Yet Another Problem On a Subsequence 解析(DP)"> <!-- toc --> # Codeforce 1000 D. Yet Another Problem On a Subsequence 解析(DP) 今天我們來看看CF1000D [題目連結](https://codeforces.com/problemset/problem/1000/D) > **題目** 略,請直接看原題 ### 前言 這題提供了我一種實用的算$C_m^n$的方法 ![](https://i.imgur.com/sPXh8LC.png) <div class="VVVcopyrightAAA";>@copyright petjelinux 版權所有<br> <a href="https://www.cnblogs.com/petjelinux/">觀看更多正版原始文章請至petjelinux的blog</a></div> ### 想法 考慮$dp[i]$為考慮到$i$位置為止的所以$subsequence$數量$+1$(一個都不選),解答就是$dp[n]-1$。 每次新考慮一個$dp[i]$時,$dp[i]$由不包含$a[i]$($a$是原數列)的$subsequence$數量加上包含$a[i]$的$subsequence$數量。而考慮包含$a[i]$的數量時,我們只需要往前找最後一個$subarray$的起點($a[j]>0$),接著使用$C_m^n$找出最後的$subarray$有幾種可能就好。 重點在於要如何計算$C_m^n$,數字太容易爆掉了。這時候我們要利用$C_m^n=C_m^{n-1}+C_{m-1}^{n-1}$,這樣就不會爆掉了,並且要特別令$C_0^0=1$,因為我們之後計算$dp$時會用到。 轉移式$:dp[i]=dp[i-1]+\sum\limits_{j=1}^{i-1}dp[j-1]\times C_{a[j]-1}^{i-j-1}$ 注意:我們令$dp[0]=1$以方便計算。而數列標號是從$1$開始。 ### 程式碼: ```cpp= inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);} const int _n=1010; int t,n,a[_n],dp[_n],C[_n][_n]; main(void) {cin.tie(0);ios_base::sync_with_stdio(0); cin>>n;rep(i,1,n+1)cin>>a[i]; rep(i,1,n+1){ C[i][0]=C[i][i]=1; rep(j,1,i)C[i][j]=(1ll*C[i-1][j]+1ll*C[i-1][j-1])%mod; }C[0][0]=1; dp[0]=dp[1]=1; rep(i,2,n+1){ dp[i]=dp[i-1]; per(j,1,i) if(a[j]>0 and a[j]<=i-j)dp[i]=(dp[i]+(1ll*dp[j-1]*C[i-j-1][a[j]-1]))%mod; } cout<<pmod(dp[n]-1,mod)<<'\n'; return 0; } ``` 標頭、模板請點Submission看 [Submission](https://codeforces.com/contest/1000/submission/92117053)