这题是个分类讨论题。
要使得没有人连续两次提议,关键在于最大值和次大值。
因此分三类情况。
记最大值为 \(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;
}
}
}
标签:cntb,因此,int,最大值,CF1569C,include,提议
From: https://www.cnblogs.com/-lilong-/p/17976882