题意:
$$用[1,2,...,n^2]填n\times n的矩阵,每个数字只能用一次,记:a_i为第i行的最小值;$$
$$S=a_1,a_2,...,a_n\cap{1,2,...,n};$$
$$求\sum_1^n|S|$$
思路:
$$考虑每个数的贡献,比如1作为最小数贡献的方案数就是n\times (\sum_1^nC_{n^2-1}^{n-1});i(i\le n)作为最小的数贡献的方案数是n\times (\sum_1^nC_{n^2-i}^{n-1})。$$$$其中组合数部分表示i作为该行的最小值出现,选择剩下的数的方案数;n表示该行可以出现在1,2,...,n行里任意一行。$$
$$然后考虑1-n这n个数的全排列和n-n^2这n^2-n个数的全排列的种数分别为n!和(n^2-n)!$$
$$综上,可以求出ans=n!\times(n^2-n)!\times n\times (\sum_{i=1}^nC_{n^2-i}^{n-1})$$
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 25000001;
const int mod = 998244353;
ll qpow(ll a, ll b, ll p)
{
ll ans = 1;
while (b)
{
if (b & 1)
ans = ans * a % p;
a = a * a % p;
b >>= 1;
}
return ans;
}
ll fac[maxn];
void init()
{
fac[0] = 1;
for (int i = 1; i < maxn; i++)
{
fac[i] = fac[i - 1] * i % mod;
}
}
ll infac(ll x)
{
return qpow(x, mod - 2, mod);
}
ll C(ll n, ll m)
{
if (n < m)
return 0;
return fac[n] * infac(fac[m]) % mod * infac(fac[n - m]) % mod;
}
int main()
{
init();
int t = 1;
scanf("%d", &t);
while (t--)
{
ll n;
scanf("%lld", &n);
ll ans = n * fac[n] % mod * fac[n * n - n] % mod;
ll sum = 0;
for (int i = 1; i <= n; i++)
{
sum += C(n * n - i, n - 1);
sum = sum % mod;
}
printf("%lld\n", ans * sum % mod);
}
return 0;
}