Educational Codeforces Round 46 D. Yet Another Problem On a Subsequence
阿新 • • 發佈:2018-06-30
mod ons ++ 數列 一個數 () -- problem dot
題目大意
- 定義一個數列是“好的”:第一個數字a[0]為數列長度+1。
- 定義一個數列的子序列是“好的”:這個子序列能分割成幾個“好的”數列。
- 各一個數列,求“好的”子序列的數目。
解題思路
- 一開始想用dp[i][j]表示[i,j]的“好的”子序列的數目。發現復雜度爆炸,而且會造成重復。
- 為了減少復雜度,避免重復。dp[i]表示後綴i,以a[i]為起始的“好的”子序列的數目。由於一個“好的”子序列能被分割。於是dp方程為:\(dp_i = \sum\limits_{j = i + a_i + 1}^{n + 1} {C_{j - i - 1}^{a_i} \cdot dp_j}\)
- 最好答案為\(\sum\limits_{i=1}^{n}{dp_i}\)
代碼
#include <bits/stdc++.h>
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define DEP(i,a,b) for(int i=(a); i>=(b); i--)
#define N 1010
using namespace std;
typedef long long LL;
const LL mod = 998244353;
int n;
LL a[N], dp[N];
LL C[N][N];
int main()
{
scanf("%d", &n);
C[0][0] = 1 ;
REP(i, 1, n+1) {
C[i][0] = C[i][i] = 1;
REP(j, 1, i)
C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
}
REP(i, 1, n+1) scanf("%lld", &a[i]);
memset(dp, 0, sizeof(dp));
dp[n+1] = 1;
DEP(i, n, 1) {
if (a[i] <= 0) {dp[i] = 0; continue;}
REP(j, i+a[i]+1 , n+2)
dp[i] = (dp[i] + (C[j-i-1][a[i]] * dp[j] % mod)) % mod;
}
LL res = 0;
REP(i, 1, n+1) res = (res + dp[i]) % mod;
printf("%lld\n", res);
return 0;
}
Educational Codeforces Round 46 D. Yet Another Problem On a Subsequence