MS 與矩陣填數(算貢獻)
阿新 • • 發佈:2022-03-15
題意
思路
這種問題一般都是劃分為若干不相交的集合,分別計算,然後再求和。在本題,就是算\(1\sim n\)每個數作為行最小數的方案數。
不失一般性,我們考察\(i\)作為行最小數的方案數。由於\(i\)可以出現在任意一行,因此方案數為\(n\)。如果\(i\)為行最小數,那麼同行的其他\(n - 1\)個數字必須比\(i\)要大,因此方案數就是從\(n^2 - i\)個數中選取\(n - 1\)個數,因此就是\(\tbinom{n^2-i}{n-1}\)。這一行中的\(n\)個數字可以任意排列,因此方案數為\(n!\)。在這一行之外的其他\(n^2 - n\)個數字也可以任意排列,因此方案數為\((n^2-n)!\)
因此最終答案為 \(\sum\limits_{i=1}^n i \cdot n \cdot \tbinom{n^2-i}{n-1} \cdot n! \cdot (n^2-n)!\)
程式碼
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 25000010; const int mod = 998244353; int main() { ll n; scanf("%lld", &n); ll t = 1; for(int i = 1; i <= n * n - n; i ++) t = t * i % mod; t = t * n % mod * n % mod; ll ans = 0; for(int i = 1; i <= n; i ++) { ll x = 1; for(int j = n * n - i - n + 2; j <= n * n - i; j ++) { x = x * j % mod; } x = x * i % mod; ans = (ans + x * t % mod) % mod; } printf("%lld\n", ans); return 0; }