D. Count the Arrays
也是一个计数题。
题目大意:
要求构造一个满足题意的数列。
- (n) 代表数列的长度
- 数列元素的范围 ([1,m])
- 数列必须有且仅有一对相同的数
- 存在一个位置 (i),使得小于 (i) 这个位置的是严格递增的,大于这个位置则是严格递减的。
这个题目也很容易把自己绕晕,所以我们要想开点。。。
不要去太细节的考虑哪一个位置放什么之类的,而是考虑如何构造满足条件的序列。
因为序列长度是 (n),范围是 (m),而且又必须有一对相同的数。
所以即从 (m) 个数里,挑出 (n-1) 个不同的数,自然而然最大的那个数就是最高点。
剩下的除了那两个相同的数之外都有两种选择,在这个最高点的左边或者右边。
对于那两个相同的数只能在最高点的两侧,所以也就没有选择。
然后有一对相同的数,所以此时有 (n-2) 种选择。
所以总的方案数就是 :(C_{m}^{n-1}*2^{n-3}*(n-2))
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=998244353;
ll c[maxn],inv[maxn];
void inv3(){
inv[1] = 1;
for (int i = 2; i < maxn; i++) {
inv[i] = (mod - mod / i)*inv[mod%i] % mod;
}
}
void init(int n){
c[0] = 1;
for (int i = 1; i <= n; i++) c[i] = c[i - 1] %mod * (n - i + 1) %mod * inv[i]%mod;
}
long long powmod(long long a, int b) {
long long ret = 1;
while (b) {
if (b & 1)ret = ret * a% mod; //b&1 �������b%2 �ĺ���һ��
a = a * a % mod;
b >>= 1;
}
return ret;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
inv3(),init(m);
if(n==2) printf("0
");
else {
ll ans=c[n-1]*powmod(2,n-3)%mod*(n-2)%mod;
printf("%lld
",ans);
}
return 0;
}