D. Count the Arrays 计数题

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\n");
	else {
		ll ans=c[n-1]*powmod(2,n-3)%mod*(n-2)%mod;
		printf("%lld\n",ans);
	}
	return 0;
} 

猜你喜欢

转载自www.cnblogs.com/EchoZQN/p/12558201.html