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;
}