Forget You
zhouyuhang · · 题解
补完番后来做一下这道题。
首先考虑
现在来看看怎么统计一个集合形成的长度为
我们先来考虑求总的方案数。套路地,写出每个集合的
代码(隐去了多项式模板):
const int N = 1e5 + 10;
int n, maxa = 0, maxb = 0;
int a[N], b[N];
vint fac, ifac;
void init(int lim) {
fac = ifac = vint(lim + 1, 1);
for (int i = 1; i <= lim; ++i) fac[i] = mul(fac[i - 1], i);
ifac[lim] = Pow(fac[lim], P - 2);
for (int i = lim; i >= 1; --i) ifac[i - 1] = mul(ifac[i], i);
}
int c(int n, int m) { return (n < m || m < 0) ? 0 : mul(fac[n], mul(ifac[m], ifac[n - m]));}
using Node = array<Poly, 2>;
queue<Node> q;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
prework();
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i] >> b[i], maxa = max(maxa, a[i]), maxb = max(maxb, b[i]);
init(maxa + maxb);
for (int i = 1, s = 0; i <= n; s = add(s, a[i]), ++i) {
Poly x(b[i] + 1), y(b[i] + 1);
int t = add(s, mul(a[i] + 1, (P + 1) / 2));
for (int j = 0; j <= b[i]; ++j) x[j] = mul(c(j + a[i] - 1, j), ifac[j]), y[j] = mul(t, mul(j, x[j]));
q.push({x, y});
}
while (q.size() > 1) {
Node u = q.front(); q.pop();
Node v = q.front(); q.pop();
q.push({u[0] * v[0], u[0] * v[1] + u[1] * v[0]});
}
Poly x = q.front()[1];
int ans = 0;
for (int i = 0, t = 1; i < x.size(); ++i, t = mul(t, i)) ans = add(ans, mul(x[i], t));
cout << ans << endl;
return 0;
}
“欢迎回来,乙坂有宇”