题目大意:个人召开会议,第个成员有项提议。先决定他们的顺序。然后按照顺序发言,如果当前人有提议,提出。否则,跳过。按顺序重复这个过程,第个人完成后再回到第个人。如果没有人连续提出提议,则这个顺序是好的.求所有好的顺序的数量。答案模 998244353。
思路:分三种情况讨论。我们计最大值为,个数为,次大值为,个数为
第一种情况:时,不管怎么排列,最终都会剩余至少两次,就会连续提议,不符合条件,结果为
第二种情况:时,不管如何排列都是符合条件的,结果为
第三种情况:并且时,对于这种情况来说,我们发现,只要在后面有一个时,就是符合条件的序列。那我们只需要考虑和的次序,显然我们发现对于这个数,只有这个数排在最后这种情况不符合,那么符合条件的概率期望为,那么对这个数的全排列来说,符合条件的排列为:
PS:习惯预处理阶乘,然后直接除以就会出错,因为预处理的阶乘是模意义下的,这就导致直接除出问题了,所以除以要转变为乘以模意义下的逆元
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;
}