• Matrix(组合数学)


    题目

    Problem - 7113

    题解

    一开始想的是dp,但是需要(dp[i][j])代表在(n imes i)的方格中放入(j)个数使得每列都至少有一个数的方案数,这样答案就是

    [n!(n^2-n)!sumlimits_{i=1}^{n}{icdot dp[i][n] cdot C(n,i)} ]

    但是计算dp复杂度是(O(n^3)),不可做。

    突破点是分别计算1~n每个数的贡献。对于数(i),当它所在行的其他数都大于(i)时对答案有1的贡献,这样的局面有(C(n^2-i,n-1) cdot n),乘(n)(i)在一行有(n)个位置可以选。此时(i)的总贡献为(C(n^2-i,n-1) cdot n)。再加上全排列,答案为

    [n!(n^2-n)!sumlimits_{i=1}^{n}{C(n^2-i,n-1) cdot n} ]

    将外面(n!(n^2-n)!)移进去可以消掉很多项,这样就不会T。

    #include <bits/stdc++.h>
    
    #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define mp make_pair
    #define seteps(N) fixed << setprecision(N) 
    typedef long long ll;
    
    using namespace std;
    /*-----------------------------------------------------------------*/
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    #define INF 0x3f3f3f3f
    
    const int N = 2.5e7 + 10;
    const int M = 998244353;
    const double eps = 1e-5;
    
    ll fact[N], rfact[N], inv[N];
    
    inline ll qpow(ll a, ll b, ll m) {
    	ll res = 1;
    	while(b) {
    		if(b & 1) res = (res * a) % m;
    		a = (a * a) % m;
    		b = b >> 1;
    	}
    	return res;
    }
    
    
    int main() {
    	IOS;
    	fact[0] = 1;
    	for(int i = 1; i < N; i++) {
    		fact[i] = fact[i - 1] * i % M;
    	}
    	int t;
    	cin >> t;
    	while(t--) {
    		int n;
    		cin >> n;
    		ll ans = 0;
    		ll tn = n * n - n;
    		ll pw = 1;
    		for(int i = 1; i <= n; i++) {
    			ans = (ans + fact[n * n - i] * n % M * n % M * pw % M) % M;
    			pw = pw * tn % M;
    			tn--;
    		}
    		cout << ans << endl;
    		
    	}
    }
    
  • 相关阅读:
    前端3 浮动布局,固定定位,绝对定位,相对定位
    前端2 字体|文本属性样式, 高级选择器
    前端1.概念
    前端,基础选择器,嵌套关系.display属性,盒模型
    数据库之索引
    数据库之进阶(视图,事务,存储过程)
    数据库,多表数据
    数据库之表的使用
    数据的演化(数据仓库的发展史)
    HDFS退出安全模式
  • 原文地址:https://www.cnblogs.com/limil/p/15227507.html
Copyright © 2020-2023  润新知