01 矩阵题解

Descirption



Solution

若定义 \(f(k)\) 为一行有 \(k\)\(1\) 的方案数,则 \(\displaystyle f(k)=\binom{m}{k}x^{m-k}y^k\)

定义 \(\displaystyle g(k)=\sum_{i=k}^{m}f(i)\)\(g(k)\) 的意义就是一行至少有 \(k\)\(1\) 的方案数。

如果 \(\min\{B_i\}=k\),那么 \(B_i=k\) 的一行有 \(f(k)\) 种方案,\(B_i>k\) 的一行有 \(g(k+1)\) 种方案,所以每行有 \(f(k)+g(k+1)\) 种方案,总方案就是 \((f(k)+g(k+1))^n-g(k+1)^n\)。注意全部 \(B_i>k\) 是不合法的,要减掉。

\(\displaystyle E=\sum_{i=0}^{m}i\cdot((f(i)+g(i+1))^n-g(i+1)^n)\)

然后就可以求啦,时间复杂度 \(\mathcal{O}(m\log n)\)

Code

#include <bits/stdc++.h>
using namespace std;
namespace Milkcat {
	typedef long long LL;
	const int N = 1e6 + 5, mod = 1e9 + 7;
	LL qpow(LL bas, LL k) {
	    LL ans = 1;
	    for (; k; bas = bas * bas % mod, k >>= 1)
	        if (k & 1) ans = ans * bas % mod;
	    return ans;
	} 
	struct Combinations {
	    LL mod, f[N], fac[N], inv[N], Finv[N];
	    void init(LL n, LL pmod) {
	        mod = pmod, inv[1] = 1, fac[0] = Finv[0] = 1;
	        for (int i = 2; i <= n; i ++)
	            inv[i] = ((mod - mod / i) * inv[mod % i]) % mod;
	        for (int i = 1; i <= n; i ++)
	            fac[i] = fac[i - 1] * i % mod, Finv[i] = Finv[i - 1] * inv[i] % mod;
	    }
	    LL operator () (LL n, LL m) {
	        if (m > n) return 0;
	        return fac[n] * Finv[m] % mod * Finv[n - m] % mod;
	    }
	} C;
	LL n, m, x, y, ans, f[N], g[N];
	int main() {
		cin >> n >> m >> x >> y, C.init(m, mod);
		for (int i = 0; i <= m; i ++)
			f[i] = C(m, i) * qpow(y, i) % mod * qpow(x, m - i) % mod;
		for (int i = m; i >= 0; i --)
			g[i] = (g[i + 1] + f[i]) % mod;
		for (int i = 0; i <= m; i ++)
			ans = (ans + i * (qpow(f[i] + g[i + 1], n) - qpow(g[i + 1], n) + mod) % mod) % mod;
		cout << ans << '\n';
		return 0;
	}
}
int main() {
    int T = 1;
    while (T --) Milkcat::main();
    return 0;
}
posted @ 2023-06-25 21:51  喵仔牛奶  阅读(29)  评论(0编辑  收藏  举报