#dp# Codeforces D. Yet Another Problem On a Subsequence

题目链接

D. Yet Another Problem On a Subsequence

time limit per test  2 seconds

memory limit per test  256 megabytes

The sequence of integers a1,a2,…,aka1,a2,…,ak is called a good array if a1=k−1a1=k−1 and a1>0a1>0. For example, the sequences [3,−1,44,0],[1,−99][3,−1,44,0],[1,−99] are good arrays, and the sequences [3,7,8],[2,5,4,1],[0][3,7,8],[2,5,4,1],[0] — are not.

A sequence of integers is called good if it can be divided into a positive number of good arrays. Each good array should be a subsegment of sequence and each element of the sequence should belong to exactly one array. For example, the sequences [2,−3,0,1,4][2,−3,0,1,4], [1,2,3,−3,−9,4][1,2,3,−3,−9,4] are good, and the sequences [2,−3,0,1][2,−3,0,1], [1,2,3,−3−9,4,1][1,2,3,−3−9,4,1] — are not.

For a given sequence of numbers, count the number of its subsequences that are good sequences, and print the number of such subsequences modulo 998244353.

Input

The first line contains the number n (1≤n≤103)n (1≤n≤103) — the length of the initial sequence. The following line contains nn integers a1,a2,…,an (−109≤ai≤109)a1,a2,…,an (−109≤ai≤109) — the sequence itself.

Output

In the single line output one integer — the number of subsequences of the original sequence that are good sequences, taken modulo 998244353.

Examples

input

3
2 1 1

output

2

input

4
1 1 1 1

output

7

Note

In the first test case, two good subsequences — [a1,a2,a3][a1,a2,a3] and [a2,a3][a2,a3].

In the second test case, seven good subsequences — [a1,a2,a3,a4],[a1,a2],[a1,a3],[a1,a4],[a2,a3],[a2,a4][a1,a2,a3,a4],[a1,a2],[a1,a3],[a1,a4],[a2,a3],[a2,a4] and [a3,a4][a3,a4].

题目描述:

给出一个长度为n的序列,问子序列(可以不连续)中存在多少个good sequence。

good sequence 的规定如下:如果一个array的长度为k,且array的第一个元素array[1]为k-1(array[1] > 0),则称这个array为good array,由一个或多个array连接组成的sequence称为good sequence 。

Solution:

dp[i] 表示以 a[i] 为首元素的good sequence的个数,故dp[i] 可以由 dp[i+1] 转化而来。

首先枚举起点 i 的位置,即从 n-1 ~ 1 倒序枚举(由于array长度最少为2,所以从n-1开始),那么对于每个当前good array的起始元素为 i 位置,假定后面可以接的其它的good array的起始元素为 a[j],对于序列长度最少为 a[i] + 1了来说,那么 j 的起始位置就是 i + a[i] + 1,终止位置为 n + 1(j = n+1 时表示此时后面不再接其它的good array),可以得出,对于当前的array来说,他的组成元素是从 j - i - 1 个元素中任选 a[i] 个。对于可选的元素为j - i - 1 个解释:容易得出,在 j 位置与 i 位置之间,一共有 j - i + 1 个元素,由于元素 a[i] 本身已经确定为当前array的首元素,而 a[j] 也已经确定为是下一个array的首元素,所以 a[i] 和 a[j] 都不能选,所以需要从 j - i - 1 个元素中选取 a[i] 个。

可以得出转移方程为:

dp[i] = c[ j - i -1][a[i] ] * dp[j]。(组合数c[i][j] 表示从 j - i - 1 这些个元素中任取出a[i]个元素)

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#define mst(a, b) memset(a, b, sizeof(a))
#define rush() int T; cin >> T; while(T--)
using namespace std;
typedef long long LL;
const int MaxN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const LL Mod = 998244353;
const double eps = 1e-9;

LL a[1005], c[1005][1005];
LL dp[1005];
int n;

void init() {
    cin >> n;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			if(j == 1) c[i][j] = i;
			else c[i][j] = (c[i-1][j] + c[i-1][j-1]) % Mod; //预处理组合数结果
		}
	}
    for(int i = 1; i <= n; i++) cin >> a[i];
}
int main() 
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);

	init();
	dp[n + 1] = 1LL; //当前array 后面不接其它的array
	LL sum = 0LL;
	for(int i = n - 1; i >= 1; i--) {
		if(a[i] <= 0) continue;
		for(int j = i + a[i] + 1; j <= n + 1; j++) {
			dp[i] += c[j-i-1][a[i]] * dp[j];
			dp[i] %= Mod;
		}
		sum = (sum + dp[i]) % Mod; //答案为每个i位置上可能的array数目之和
	}
	cout << sum << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jasmineaha/article/details/81176012