zoukankan      html  css  js  c++  java
  • 【2020.9.12 NOIP模拟赛 T3】普及组

    题目链接

    求矩阵的所有行和列的乘积均为 (k) 的方案数。要求矩阵是 (n imes n) 的,由整数组成(可负)。(T le 2 imes 10^5,n le 5 imes 10^6),每组数据的 (k) 已知,质因数不超过二次。

    首先符号的贡献显然是独立的,(k=1) 的贡献显然是 (2^{(n-1)^2})(考虑前 ((n-1) imes (n-1)) 随便填,用剩下一行一列来调整)。那么剩下我们要做的就是计算出正整数的贡献。

    考虑到 (k = 31 imes 37^2)(k = 2 imes 3^2) 等价。具体地说,答案只与 (k) 的一次质因数和二次质因数的个数有关。而质因数之间又是独立的。

    首先考虑一次质因数的情况。那么我们要做的就是在 (n imes n) 的网格中每行每列都只填一个 1 的方案数。这是个组合数学的入门题,答案是 (n!)

    然后考虑二次质因数的情况。那么我们要做的就是在 (n imes n) 的网格中填若干 (1)(2),使得每行每列的和为 (2)。题解中有一个转化为图论问题用生成函数多项式求逆求解的方法,并不会。

    考虑最后一列填的什么。如果填的是 (2),那么删去最后一列和那一行能够转化成子问题;如果填的是两个 (1),那么如果这两行的另一个 (1) 恰好是在同一列,那么合并并挪到最下面能够与最右边列是一个 (2) 的情况一一对应;如果不同,将那两行合并并放到最下面,能够与最右边列是两个 (1) 的情况映射,注意这里的删除合并是二对一的关系(左上右下或左下右上)。

    (f(n)) 表示 (n imes n) 矩阵最右边列为一个 (2) 的方案数;(g(n)) 表示 (n imes n) 矩阵最右边列是两个 (1) 的方案数。那么转移为:

    [f(n) gets n(f(n-1)+g(n-1)) ]

    [g(n) gets {n choose 2} (f(n-1)+2g(n-1)) ]

    [Ans(n) gets f(n)+g(n) ]

    关键代码

    inline void init() {
    	f[1] = 0, g[1] = 1;
    	for (register int i = 2; i <= 5e6; ++i) {
    		g[i] = 1ll * i * (g[i - 1] + f[i - 1]) % P;
    		f[i] = (1ll * i * (i - 1) / 2) % P * ((f[i - 1] << 1) + g[i - 1]) % P;
    	}
    }
    int main() {
    	...
    	init();
    	int _; read(_); 
    	while (_--) {
    		int n; read(n);
    		ll ans = quickpow(jie[n], can1) * quickpow((f[n] + g[n]) % P, can2) % P;
    		ans = ans * quickpow(2, 1ll * (n - 1) * (n - 1) % (P - 1)) % P;
    		printf("%lld
    ", (ans % P + P) % P);
    	}
        return 0;
    }
    
  • 相关阅读:
    String、StringBuffer与StringBuilder之间区别
    关于 hashCode() 你需要了解的 3 件事
    Java基础之 运算符
    Java基础之基础语法
    Java基础之Java 修饰符
    自动化-python介绍与基础
    vue访问本地后台
    vue请求报错Uncaught (in promise)
    使用vue-resource,get、post、jsonp都报未定义的错误。
    【蓝桥杯】历届试题 打印十字图
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13667041.html
Copyright © 2011-2022 走看看