先考虑一下如果每个数都不是相同的情况,先从小到大排序,假如我们已经排了前s个人,且有j人在第一排,我们只需要保证第一排的的人数一直大于等于第二排就可以满足题目列递增,且行递增的要求了。
如果存在一些数相同,我们把这些数当成一个点,状态转移的时候枚举一下这个数里有多少数在第一排即可。
最后答案再乘上各个数个数的阶乘就可以了。
AC代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5010,mod=998244353;
int n;
int mp[N];
int dp[N][N];
int get(int x){
int res=1;
for(int i=1;i<=x;i++)res=res*i%mod;
return res;
}
main(){
cin>>n;
for(int i=0;i<n;i++){
int x;
cin>>x;
mp[x]++;
}
vector<int>q;
for(int i=1;i<=n;i++)
if(mp[i]) q.push_back(mp[i]);
dp[0][0]=1;
int s=0;
for(auto i:q){
s+=i;
for(int j=min(n/2,s);j>=s-j;j--)
for(int k=0;k<=i&&k<=j;k++)
dp[s][j]=(dp[s][j]+dp[s-i][j-k])%mod;
}
int ans=dp[n][n/2];
//cout<<ans<<"*****"<<endl;
for(auto x:q) ans=ans*get(x)%mod;
cout<<ans<<endl;
}