[CF-Edu113]C. Jury Meeting

[CF-Edu113]C. Jury Meeting

题目

(n)个人,第(i)个人有(a_i)句话要说,你可以安排一个发言顺序(是一个(1sim 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
" , fac[n]);
		} else {
			printf("%d
" ,(
			           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;
}
原文地址:https://www.cnblogs.com/dream1024/p/15254255.html