CF1569C

这题是个分类讨论题。

要使得没有人连续两次提议,关键在于最大值和次大值。

因此分三类情况。

记最大值为 \(a\),出现次数 \(cnta\),次大值 \(b\),出现次数 \(cntb\)

  • \(cnta \ge 2\)

最大值不止一个,说明有多个人会同时在第 \(a\) 轮结束,因此无论任何情况都不会有人连续两次提议。任何顺序均可,因此答案为 \(n!\)

  • \(a-b \ge 2\)

在进行了 \(b\) 轮后,\(a\) 还剩多于一个提议,但已经没有其他人了,因此不得不连续两次提议,不符合要求,因此答案为 \(0\)

  • \(a-b = 1\)

不难发现,只有当 \(a\) 在所有次大值的右边的时候,才不得不连续两次提议。因此,原来 \(a\) 的位置有 \(cntb+1\) 个选择,现在剩下 \(cntb\) 个,因此求完 \(n!\) 后要乘 \(\dfrac{cntb}{cntb+1}\)。答案为 \(\dfrac{n! \times cntb}{cntb+1}\)

代码实现如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#define int long long
#define MOD 998244353

using namespace std;
int n,a[1000001],ans,cnt;
signed main()
{
	int T;
	cin >> T;
	while( T-- )
	{
		ans = 1,cnt = 1;
		cin >> n;
		for( int i = 1 ; i <= n ; i++ )
			cin >> a[i];
		sort( a + 1 , a + n + 1);
		if ( a[n] - a[n-1] >= 2) cout << 0 <<endl;
		else if ( a[n] == a[n-1] )
		{
			for( int i = 1 ; i <= n ; i++ ) 
				ans = ans * i % MOD;
			cout << ans << endl;
		}
		else
		{
			int i;
			for( i = n - 1 ; i >= 1 && a[i] == a[i-1]; i-- );
			i = n - i;
			for( int j = 1 ; j <= n ; j++)
				if( j != i + 1) ans = ans * j % MOD;
			cout << ans * i % MOD << endl;
		}
	}
}
posted @ 2024-01-20 17:59  liyilang2021  阅读(2)  评论(0编辑  收藏  举报