1 条题解
-
0
自动搬运
来自洛谷,原作者为

DreamLand_zcb
此生无悔入MC,来世还做方块人!搬运于
2025-08-24 22:41:34,当前版本为作者最后更新于2023-10-08 22:46:19,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
思路
设状态 其中 表示前 个数中,有 个折点的方案数。
考虑状态转移,显然 只能影响到 、、,证明如下:
首先需要确定,在原序列中插入第 个数,这个 是所有数中最大的,所以只要在非头/尾部插入这个点,这个点一定就是新的折点。
-
表示插入第 个点后没有新增折点:
例:

情况一如图,当 插入波峰 左右侧时, 不再是折点,折点变成了 ,此时折点数不变。

情况二如图,当 插入序列头尾 左右时, 依然不是折点,序列没有新增折点,此时折点数不变(如果头或尾的点是向下走的那么插入后新增了一个点,不属于该范围,此时只有在其中一边插入 才能满足不增加新折点)。
总结一下,当 为奇数,总共 种可能。当 为偶数,总共 中可能,所以转移方程:
-
表示插入第 个点后新增了一个转折点。
只有一种情况,即当在序列头和尾向下走时在头和尾前后插入 只增加一个转折点,如图, 为新增的一个转折点。

所以转移方程:
-
表示插入第 个点后新增了两个转折点。
显然在除了以上所有情况,其他地方插入 都会新增两个折点,转移方程:
$$dp[i+1][j+2] = dp[i][j] \times (i + 1 - (j + 1) - 2) $$
初始值:、。
答案:。
代码
#include <bits/stdc++.h> #define ll long long #define setp setprecision #define mem(a, m) memset(a, m, sizeof(a)) using namespace std; const int MOD = 123456; int n, k; int dp[505][505]; int mod(int a) { return a % MOD; } int main() { ios::sync_with_stdio(false); cin >> n >> k; dp[1][0] = 1; for(int i=2;i<n;i++) { dp[i][0] = 2; for(int j=0;j<=i;j++) { dp[i+1][j] += mod(dp[i][j] * (j + 1)); dp[i+1][j+1] += mod(dp[i][j] * 2); dp[i+1][j+2] += mod(dp[i][j] * (i - j - 2)); } } cout << dp[n][k-1] % MOD; return 0; } -
- 1
信息
- ID
- 7893
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者