题意
找到一种序列,按序减一,如果没有出现同一个位置连续减两次,即为good,问一共有多少种。
思路
设max 最大值的个数, min次大值的个数
情况1:有大于或等于两个最大值,那任意排都可
情况2:max-min== 0 ,任意排都可
情况3:若max-min==1 那必须保持最大值不能在最后,不然会出现连减两次,
那也就是要最后一个次大值之后不能有最大值。设cnt为次大值的个数,那满足的这种要求的序列的概率为 cnt / (cnt+1);即不要排在最后即可。
代码
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef pair<string,string>pss;
typedef pair<int,int> pii;
const ll mod=998244353;
#define mem(a,n) memset(a,n,sizeof a)
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
const int inf=0x3f3f3f3f;
const int N =5e5+7;
ll gcd(ll a,ll b){ll d; while(b){ d=b; b=a%b; a=d; } return a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
const ll MOD = 998244353;
const ll MAXN = 5e5 + 3;
ll fac[MAXN];
ll inv[MAXN];
ll QPow(ll x, ll n){
ll ret = 1;
ll tmp = x % MOD;
while (n){
if (n & 1){
ret = (ret * tmp) % MOD;
}
tmp = tmp * tmp % MOD;
n >>= 1;
}
return ret;
}
void init(){
fac[0] = 1;
for (int i = 1; i < MAXN; i++){
fac[i] = fac[i - 1] * i % MOD;
}
inv[MAXN - 1] = QPow(fac[MAXN - 1], MOD - 2);
for (int i = MAXN - 2; i >= 0; i--){
inv[i] = inv[i + 1] * (i + 1) % MOD;
}
}
int a[N];
map<int,int>mp;
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
init();
while(t--){
mp.clear();
int n;cin>>n;
rep(i,1,n){
cin>>a[i];
mp[a[i]]++;
}
sort(a+1,a+n+1);
if(mp[a[n]]>=2){
cout<<fac[n]<<endl;
}
else if(a[n]==a[n-1]){
cout<<fac[n]<<endl;
}
else if(a[n]-a[n-1]==1){
ll ans=fac[n];
ans=(ans*mp[a[n-1]])%mod*QPow(mp[a[n-1]]+1,MOD-2)%MOD;
cout<<ans%MOD<<endl;
}
else cout<<"0"<<endl;
}
}