大致题意:给你一个n * n 的矩阵填充了[1 , n2] 的数,每一行都会贡献一个最小值ai,S = {a1,a2,…,an} ∩ {1,2,…,n} 求ΣS
一行的最小值是1~n中的数时,才对答案有贡献。
首先从1~n枚举一行的最小值 记为i
这一行剩余n-1个数都要比i大,所以有C(n * n - i ,n-1)种选法
然后把这一行的n个数全排列 n!
剩余的n * n - n个数填到剩下的n-1行中,随意排列 共(n * n - n)!种排法
把之前带有i的那一行插进去,组成n行 共n种方法
然后这个排法保证最小值 i 对答案有贡献 即+1
所以有多少排法 答案就加多少
对于每一个 i ,排法有: C(n * n - i ,n-1)* n! * (n * n - n)!* n
则总排法:
for (int i = 1; i <= n; i ++ )
{
int now = C(n * n - i , n - 1) * f[n] % mod * f[n * n - n] % mod * n % mod;///f数组是阶乘数组
res = (res + now) % mod;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
ll f[25000010];
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
ll C(ll n,ll m)
{
ll ans=1;
ans=ans*f[n]%mod;
ans=ans*qpow(f[m],mod-2)%mod;
ans=ans*qpow(f[n-m],mod-2)%mod;
return ans;
}
int main()
{
f[0]=1;///wa点
f[1]=1;
for(ll i=2; i<=25000005; i++)f[i]=f[i-1]*i%mod;
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
ll res=0;
for(int i=1; i<=n; i++)
{
ll now = C(n * n - i, n - 1) * f[n] % mod * f[n * n - n] % mod * n % mod; ///f数组是阶乘数组
res = (res + now) % mod;
}
cout<<res<<endl;
}
return 0;
}