题目链接: https://codeforces.com/problemset/problem/1312/D
题意:
计算数组的数量使得:
每个数组包含 n 个元素
每个元素都是 1 到 m 的整数
每个数组恰好有一对相等的元素
每个数组 a 都存在一个索引 i , 使得该数组在第 i 个元素之前严格升序并在它之后严格降序
思路: 由题意可知, 数组的长度为 n, 且有一个最大元素, 也有一对恰好相等的元素. 先不考虑这一对相等的元素, 考虑剩下的 n - 1 个元素, 我们需要选出 n - 1 个元素, 此时的方案数为 C m n − 1 C_m^{n - 1} Cmn−1 .
其中最大的数显然是索引 i , 那么这一对相等的数将从剩下的 n - 2 个元素中选一个作为相等元素的数, 此时的方案数为 n − 2 n-2 n−2 , 最后就是决定一个数在最大数的左边还是右边, 因为每个数(除了那一对相等元素) 都是不同的, 那么不论他们在左边还是右边都可以形成严格升序和降序, 所以贡献的方案数为 2 n − 3 2^{n - 3} 2n−3, 最后答案相乘即可: C m n − 1 ∗ 2 n − 3 ∗ ( n − 2 ) C_m^{n-1} * 2^{n-3} * (n-2) Cmn−1∗2n−3∗(n−2)
AC代码
public class Main {
public static final int M = 200005;
public static int mod = 998244353;
public static long[] invFact = new long[M];
public static long[] fact = new long[M];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n, m;
n = in.nextInt();
m = in.nextInt();
getInvArray();
long ans = 1L;
ans *= fact[m] % mod * invFact[n - 1] % mod * invFact[m - n + 1] % mod;
ans %= mod;
ans *= ksm(2L, (n - 3) * 1L);
ans %= mod;
ans *= (n - 2);
ans %= mod;
System.out.println(ans);
in.close();
}
public static Long ksm(Long n, Long m) {
Long ans = 1L;
while(m > 0) {
if((m & 1) == 1) {
ans *= n;
ans %= mod;
}
n = n * n % mod;
n %= mod;
m >>= 1;
}
return ans % mod;
}
public static Long getInv(Long x) {
return ksm(x, (mod - 2) * 1L);
}
public static void getInvArray() {
fact[0] = 1L;
invFact[1] = invFact[0] = 1L;
for(int i = 1; i < M; i++) {
fact[i] = i * fact[i - 1] % mod;
}
for(int i = 2; i < M; i++) {
invFact[i] = invFact[i - 1] * getInv(i * 1L) % mod; // 阶乘逆元
}
}
}