题目传送门
sol:首先我们考虑在一个长度为$n$的序列里只有一个数出现了两次其他数都只出现了一次,那么在序列中出现过的数就有$n - 1$个。而这些数的范围是$[1, m]$,从$[1, m]$里选$n - 1$个不同的数的方案数为$C_{m}^{n - 1}$。这$n - 1$个数里最大的数不能作为出现两次的数,否则就没有峰值了,所以可以作为出现两次的数有$n - 2$个。再考虑这些数的排列,出现两次的数肯定要一个在峰值左边一个在峰值右边,除了出现两次的数和峰值以外还剩$n - 3$个数,这些数可以在峰值左边也可以在峰值右边,所以有$2^{n - 3}$种情况。最终的结果就是$C_{m}^{n - 1}*(n - 2)*(2^{n - 3})$。另外在特判一下$n$是2的情况,如果$n$是2又出现了一对重复的数是没有峰值的,所以结果一定是$0$。
- 排列组合
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MOD = 998244353; int quick_pow(int n, int k) { int res = 1; while (k) { if (k & 1) res = 1LL * res * n % MOD; n = 1LL * n * n % MOD; k >>= 1; } return res % MOD; } int main() { int n, m; scanf("%d%d", &n, &m); if (n == 2) return puts("0") * 0; int ans = 1LL * (n - 2) * quick_pow(2, n - 3) % MOD; int tmp1 = 1, tmp2 = 1; for (int i = 1; i <= n - 1; i++) { tmp1 = 1LL * tmp1 * (m - i + 1) % MOD; tmp2 = 1LL * tmp2 * i % MOD; } ans = 1LL * ans * tmp1 % MOD; ans = 1LL * ans * quick_pow(tmp2, MOD - 2) % MOD; printf("%d ", ans); return 0; }