题目
题意:
给你m个数,让其在一个长度为n的数组中排列,但是要保证先是单调递增,然后是单调递减,并且有两个元素是一样的。
思路:
首先我们要从m中选出n-1个元素排列 C ( n , m ) C(n, m) C(n,m),因为有两个元素一样,所以要n-1,在这些元素里面我们要选择一个元素是一样的,这个时候可能会有n-1种,但是如果选择了这些元素中的最大值,那么就无法满足单调递增,所以选择一样的元素只有n-2种 ,然后就是选择位置了,位置的话,我们可以把最大值看成固定的,这样的话我们可以发现出了那两个一样的元素之外,其他的元素既可以放在左边也可以放在右边,那么就有n-3个这样的元素,所以排列的方式就有 2 n − 3 2^{n-3} 2n−3,然后全部乘起来,答案就出来了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
typedef vector<int> vec;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
const int mod = 998244353;
const int maxn = 2e5 + 10;
ll fac[maxn];
ll quickpow(ll a, ll b) {
ll ans = 1, base = a;
while (b) {
if (b & 1) ans = ans * base % mod;
base = base * base % mod;
b >>= 1;
}
return ans;
}
ll inv(ll x) {
return quickpow(x, mod - 2);
}
ll C(int n, int m) {
return fac[n] * inv(fac[m] * fac[n - m] % mod) % mod;
}
int main() {
int n, m;
read(n), read(m);
if (n == 2) {
out(0);
return 0;
}
fac[1] = 1;
for (int i = 2; i <= m; i++) {
fac[i] = (fac[i - 1] * i) % mod;
}
ll x = C(m, n - 1);
x = x * (n - 2) % mod;
x = x * quickpow(2, n - 3) % mod;;
out(x);
return 0;
}