题意:
给我们长度是
n
−
1
n-1
n−1的
b
b
b数组。其中
b
i
b_i
bi满足:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210417162021145.png)
其中 a a a数组是 1 n 1~n 1 n的排列,让我们求有多少种 n n n的排列对应得 b b b数组是题目所给得数组。
题解:
这是个计数 D P DP DP问题。
我们这里定义 d p [ i ] [ j ] dp[i][j] dp[i][j]表示前 i i i个数的排列,第 i i i个位置放的数是第 j j j小的方案数。
那么如果 b [ i − 1 ] = 0 b[i-1]=0 b[i−1]=0,也就是 a [ i ] > a [ i − 1 ] a[i]>a[i-1] a[i]>a[i−1],对应的:
d p [ i ] [ j ] = ∑ d p [ i − 1 ] [ k ] , 1 ≤ k ≤ j − 1 dp[i][j]=\sum dp[i-1][k],\ 1\leq k\leq j-1 dp[i][j]=∑dp[i−1][k], 1≤k≤j−1
如果 b [ i − 1 ] = 1 b[i-1]=1 b[i−1]=1,那么 a [ i ] < a [ i − 1 ] a[i]<a[i-1] a[i]<a[i−1],对应的:
d p [ i ] [ j ] = ∑ d p [ i − 1 ] [ k ] , j ≤ k ≤ i − 1 dp[i][j]=\sum dp[i-1][k],\ j\leq k\leq i-1 dp[i][j]=∑dp[i−1][k], j≤k≤i−1
实现细节见代码:
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int MAXN = 5010;
const int mod = 1e9 + 7;
ll b[MAXN], dp[MAXN][MAXN];
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
memset(dp, 0, sizeof dp);
for (int i = 1; i < n; i++) {
cin >> b[i];
}
dp[1][1] = 1;
for (int i = 2; i <= n; i++) {
ll sum = 0;
if (b[i - 1] == 0) {
for (int j = 1; j <= i; j++) {
dp[i][j] = sum;
sum = (sum + dp[i - 1][j]) % mod;
}
}
else {
for (int j = i - 1; j >= 1; j--) {
sum = (sum + dp[i - 1][j]) % mod;
dp[i][j] = sum;
}
}
}
ll ans = 0;
for (int i = 1; i <= n; i++) {
ans = (ans + dp[n][i]) % mod;
}
cout << ans << endl;
}
return 0;
}