[CF-Edu113]C. Jury Meeting

[CF-Edu113]C. Jury Meeting

题目

\(n\)个人,第\(i\)个人有\(a_i\)句话要说,你可以安排一个发言顺序(是一个\(1\sim n\)的排列),如果有人有话说,就进行发言,轮到第\(i\)个人时,若TA有话说,就说一句,不然就跳过.一个发言顺序良好,当且仅当任何一个人不会连续发言,问良好的发言顺序的数量,取模.

没想到in a row还可以翻译成连续

思路

题目说的这么绕,简化一下吧.

\(a\)数组的最大值出现了\(num1\),次大值出现了\(num2\)次,若\(num1 > 1\),不管怎么排列都是合法的,方案数就是\(n!\).否则,又有两种情况:①最大值减次大值大于1,不管怎么都是不合法的,输出0;②最大值恰好比次大值大1,这也是需要我们详细讨论的.

我们单独把\(a\)的最大值和次大值单独拿出来分析:

一个顺序要是合法,最大值就不能放在最后面(注意这里"最后"的含义,已经忽略了最大值次大值以外的东西),显然,不合法的排列方案数就是\(num2!\)(最大值要放在最后面).

最大值次大值以外的,是可以随便排的,方案数是\((n-num1-num2)!\).

然后把两个排列合并起来,使原来在同一个排列的两个元素相对顺序不改变(我语文不好),的方案数就是\(C_n^{num2+num1}\)(具体可以看这个:[ABC217]F - Make Pair).

综上,这个情况的答案就是\(num2!\cdot (n-num1-num2)! \cdot \frac{n!}{(num2+num1)!\ (n-num2-num1)!}=num2!\cdot \frac{n!}{(num2+num1)!}\)

代码

#include <iostream>
#include <cstdio>
using namespace std;

template <class T>
T read() {
	T re = 0;
	char c = getchar();
	bool negt = false;
	while(c < '0' || c > '9')
		negt |= (c == '-') , c = getchar();
	while(c >= '0' && c <= '9')
		re = (re << 1) + (re << 3) + c - '0' ,c = getchar();
	return negt ? -re : re;
}

typedef long long LL;
const LL mod = 998244353;
const int N = 200010;

int n;
int a[N];
LL fac[N] , inv[N];

LL Pow(LL a , int p) {
	LL res = 1;
	while(p) {
		if(p & 1)
			res = res * a % mod;
		a = a * a % mod;
		p >>= 1;
	}
	return res;
}
int main() {
	fac[0] = inv[0] = 1;
	for(int i = 1 ; i < N ; i++)
		fac[i] = fac[i - 1] * i % mod;
	for(int i = 1 ; i < N ; i++)
		inv[i] = Pow(fac[i] , mod - 2);

	int T = read<int>();
	while(T--) {
		n = read<int>();
		for(int i = 1 ; i <= n ; i++)
			a[i] = read<int>();
		int maxa = 0;
		for(int i = 1 ; i <= n ; i++)
			if(maxa < a[i])
				maxa = a[i];

		int num1 = 0 , num2 = 0;
		for(int i = 1 ; i <= n ; i++)
			if(a[i] == maxa)
				++num1;
			else if(a[i] == maxa - 1)
				++num2;

		if(num1 > 1) {
			printf("%d\n" , fac[n]);
		} else {
			printf("%d\n" ,(
			           fac[n] -
			           fac[num2]
			           * fac[n - num2 - 1] % mod
			           * fac[n] % mod
			           * inv[num2 + 1] % mod
			           * inv[n - num2 - 1] % mod

			           + mod) % mod
			      );
		}
	}
	return 0;
}
posted @ 2021-09-11 12:01  追梦人1024  阅读(48)  评论(0编辑  收藏  举报