原题传送门
题目大意: n n n个人召开会议,第 i i i个成员有 a i a_i ai?项提议。先决定他们的顺序。然后按照顺序发言,如果当前人有提议,提出。否则,跳过。按顺序重复这个过程,第 n n n个人完成后再回到第 1 1 1个人。如果没有人连续提出提议,则这个顺序是好的.求所有好的顺序的数量。答案模 998244353。
思路:分三种情况讨论。我们计最大值为 m x mx mx,个数为 t o t tot tot,次大值为 m x ′ mx' mx′,个数为 c n t cnt cnt
第一种情况: m x ? m x ′ > 1 mx-mx'>1 mx?mx′>1时,不管怎么排列,最终 m x mx mx都会剩余至少两次,就会连续提议,不符合条件,结果为 0 0 0
第二种情况: t o t > 1 tot>1 tot>1时,不管如何排列都是符合条件的,结果为 n ! n! n!
第三种情况: m x = m x ′ + 1 mx=mx'+1 mx=mx′+1并且 t o t = 1 tot=1 tot=1时,对于这种情况来说,我们发现,只要在 m x mx mx后面有一个 m x ′ mx' mx′时,就是符合条件的序列。那我们只需要考虑 m x mx mx和 m x ′ mx' mx′的次序,显然我们发现对于这 c n t + 1 cnt+1 cnt+1个数,只有 m x mx mx这个数排在最后这种情况不符合,那么符合条件的概率期望为 c n t c n t + 1 \frac{cnt}{cnt+1} cnt+1cnt?,那么对这 n n n个数的全排列来说,符合条件的排列为: n ! c n t c n t + 1 n!\frac{cnt}{cnt+1} n!cnt+1cnt?
PS:习惯预处理阶乘,然后直接除以 c n t + 1 cnt+1 cnt+1就会出错,因为预处理的阶乘是模 m o d mod mod意义下的,这就导致直接除出问题了,所以除以 c n t + 1 cnt+1 cnt+1要转变为乘以模 m o d mod mod意义下的逆元
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10,mod=998244353;
typedef long long ll;
ll t,n,a[N],fac[N];
ll power(ll a,ll b){
ll res=1;for(;b;b>>=1){
if(b&1) res=res*a%mod;a=a*a%mod;}return res;
}
int main(){
cin>>t;while(t--){
cin>>n;ll maxn=0;fac[0]=1;for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;for(int i=1;i<=n;i++) {
cin>>a[i];maxn=max(maxn,a[i]);}ll cnt=0,tot=0;for(int i=1;i<=n;i++){
if(a[i]==maxn) tot++;if(a[i]==maxn-1) cnt++;}if(tot>1) cout<<fac[n]<<endl;else if(tot==1&&cnt!=0) cout<<fac[n]*cnt%mod*power(cnt+1,mod-2)%mod<<endl;else cout<<"0"<<endl;}return 0;
}