题目描述
wlswls有一个整数nn,他想请你算一下有多少1...n1...n的排列(permutation)满足:对于所有的i(2 \le i \le n)i(2≤i≤n),若ii为奇数,则a[i - 1] < a[i]a[i−1]<a[i],否则a[i - 1] > a[i]a[i−1]>a[i]。请输出答案mod 1e9 + 7。
输入描述
一行一个整数nn。
1 \le n \le 10001≤n≤1000
输出描述
一行一个整数表示答案。
样例输入 1
3
样例输出 1
2
//在i为偶数时候,我们k是从j->i-1。这里解释以下
//正常k是从j+1->i,这里我们来举个例子
//假设一个排列{1,3,2},那么dp[4][2]是要把2放在最后面,那么我们可以把排列中
//大于等于2的数加1即得到排列{1,4,3},这样不会改变关系,再把2放进去就得到{1,4,3,2}了。
//所以我们要求dp[i][j]=(dp[i-1][i-1]+.....+dp[i-1][j]) 当i是偶数时候
//因为上一次排列中大于j的数都隐性加了1(实际没加),但是不改变关系
//所以我们k是从j->i-1.
//dp[4][1]=dp[3][1]+dp[3][2]+dp[3][3] (dp[3][1]的情况+dp[3][2]的情况+dp[3][3]的情况)
可以用前缀和优化一个On。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
const int MOD = 1e9 + 7;
typedef long long ll;
ll dp[1010][1010];
int sum[maxn];
int main()
{
//freopen("C://input.txt", "r", stdin);
int n;
scanf("%d", &n);
dp[1][1] = 1;
for (int i = 2; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
if (i & 1)//奇数,升序 从1->(j-1)转移
{
for (int k = 1; k <= j-1 ; k++)
{
dp[i][j] =dp[i][j]%MOD + dp[i - 1][k]%MOD;
}
}
//dp[i][j] = (dp[i][j - 1] + dp[i - 1][j - 1] + MOD) % MOD;//前缀和优化
else
{
//偶数,降序 从j -> i-1转移
for (int k = j; k<=i-1; k++)
{
dp[i][j] = dp[i][j] % MOD + dp[i - 1][k] % MOD;
}
//dp[i][j] = (dp[i][j - 1] + dp[i - 1][i - 1] - dp[i - 1][j - 1] + MOD) % MOD;
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
{
ans =ans%MOD+ dp[n][i]%MOD;
}
printf("%d\n", ans);
return 0;
}