SDOI2010 地精部落
SDOI2010 地精部落
题意
求所有数都是波峰或者波谷的\(1-N\)序列个数
\(3 \leq N \leq 4200\)
分析
借鉴以前学习的插入型DP的思想。
容易发现把第一个数设置为波谷和波峰得到的答案是一样的,所以不妨令第一个数为波峰
\(dp[i]\)表示\(1-i\)的序列个数,现在要插入\(i + 1\),那么\(i + 1\)一定会是波峰,插入的位置就必须在奇数位置的右边
不难得出转移方程
\(dp_i = \sum \tbinom{i - 1}{j - 1}dp_{j-1}\times dp_{i-j}\)
代码
实现上注意这题模数给定,不要用快速幂求逆元的方法,直接递推即可
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
typedef long long ll;
ll rd(){
ll x;
scanf("%lld",&x);
return x;
}
const int maxn = 1e4 + 5;
int C[2][maxn];
int MOD;
int main(){
int n = rd();
MOD = rd();
vector<int> dp(n + 1);
dp[0] = 1;
C[0][0] = C[1][0] = 1;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= i;j++){
if(j & 1) dp[i] += (ll)dp[j - 1] * dp[i - j] % MOD * C[1 ^ (i & 1)][j - 1] % MOD,dp[i] %= MOD;
C[i & 1][j] = (C[(i & 1) ^ 1][j - 1] + C[(i & 1) ^ 1][j]) % MOD;
}
}
cout << dp[n] * 2 % MOD;
}