[QOJ4533] 灯泡测试 题解
[QOJ4533] 灯泡测试 题解
如果只有两个灯泡,要求第一个灯泡比第二个灯泡早爆炸,那么答案就是:
\[\int_{-\infty}^{\infty}-f'_1(t)f_2(t)\text dt
\]
因为 \(f(t)\) 表示寿命大于 \(t\) 的概率,所以它的导数的相反数就是寿命 \(= t\) 的概率。
如果有 \(n\) 个灯泡,询问 \((1, v+1)\),答案就是:
\[\begin{aligned}
&\int_{-\infty}^{\infty} f'_1(t)\sum_{S\subseteq\{1, 2,...,n\},|S| = v }\prod_{i\in S} (1 - f_i(t))\prod_{i\notin S} (f_i(t))\text{d}t\\
=&\int_{-\infty}^{\infty} f'_1(t)[w^v]\prod_i(1-f_i(t)+f_i(t)w)\text{d}t\\
\end{aligned}
\]
因为 \(f\) 是分段函数,我们考虑所有 \(f\) 的分割点,将实数域分为了 \(n + 1\) 部分,每一部分单独考虑,也就是说从小往大考虑所有 \(T_i\),将 \(i\) 对应的背包项从 \(w\) 改为 \(1-f_i(t)+f_i(t)w\),这里记录有多少个单独 \(w\) 的项,将多项式统一除掉这么多 \(w\) 方便计算:
\[\begin{aligned}
=&\int_{T_k}^{T_{k + 1}} (e^{-\lambda_1(t - T_1)})
'[w^v]\prod_{T_i\ge k}(1-e^{-\lambda_i(t - T_i)}+e^{-\lambda_i(t - T_i)}w)\mathrm{d}t\\
=&\int_{T_k}^{T_{k + 1}} -\lambda _1e^{\lambda_1 T_1-\lambda_1t}[w^v]\prod_{T_i\ge k}(1-e^{-\lambda_it +\lambda_i T_i}+e^{-\lambda_it +\lambda_i T_i}w)\mathrm{d}t\\
=-\lambda _1e^{\lambda_1 T_1}&\int_{T_k}^{T_{k + 1}}
e^{-\lambda_1t}
[w^v]\prod_{T_i\ge k}(1-e^{-\lambda_it +\lambda_i T_i}+
e^{-\lambda_it +\lambda_i T_i}w)\text{d}t\\
\end{aligned}
\]
发现 \(e^{-t}\) 一直出现,考虑换元为 \(x\)。
\[\begin{aligned}
-\lambda _1e^{\lambda_1 T_1}&\int_{T_k}^{T_{k + 1}} e^{-\lambda_1t}[w^v]\prod_i(1-e^{-\lambda_it +\lambda_i T_i}+e^{-\lambda_it +\lambda_i T_i}w)\text{d}t\\
=-\lambda _1e^{\lambda_1 T_1}&\int_{T_k}^{T_{k + 1}} e^{-\lambda_1t}[w^v]\prod_i(1-e^{-\lambda_it +\lambda_i T_i}+e^{-\lambda_it +\lambda_i T_i}w)\dfrac {\text{d}t}{\text d(e^{-t})}\text d(e^{-t})\\
=-\lambda _1e^{\lambda_1 T_1}&\int_{T_k}^{T_{k + 1}} e^{-\lambda_1t}[w^v]\prod_i(1-e^{-\lambda_it +\lambda_i T_i}+e^{-\lambda_it +\lambda_i T_i}w) \dfrac 1{-e^{-t}}\text d(e^{-t})\\
=-\lambda _1e^{\lambda_1 T_1}&\int_{e^{-T_{k +1}}}^{e^{-T_k}} x^{\lambda_1}[w^v]\prod_i(1-x^{\lambda_i}e^{\lambda_iT_i}+x^{\lambda_i}e^{\lambda_iT_i}w) (-\dfrac 1{x})\text dx\\
=\lambda _1e^{\lambda_1 T_1}&\int_{e^{-T_{k +1}}}^{e^{-T_k}} x^{\lambda_1-1}[w^v]\prod_i(1-x^{\lambda_i}e^{\lambda_iT_i}+x^{\lambda_i}e^{\lambda_iT_i}w) \text dx\\
\end{aligned}
\]
用二维背包维护连乘式,设连乘式乘上 \(x^{\lambda _1 - 1}\) 和前文所少乘的 \(w\) 代表的二元多项式为 \(A\),容易计算出 \(f_{i, j} = [x^iw^j]A\)。
\[\begin{aligned}
\lambda _1e^{\lambda_1 T_1}&\int_{e^{-T_{k +1}}}^{e^{-T_k}} [w^v]\sum_{u, v}f_{u, v}x^uw^v\ \text dx\\
=\lambda _1e^{\lambda_1 T_1}&\int_{e^{-T_{k +1}}}^{e^{-T_k}} \sum_{u}f_{u, v}x^u\ \text dx\\
=\lambda _1e^{\lambda_1 T_1}&\sum_{u}f_{u, v}\int_{e^{-T_{k +1}}}^{e^{-T_k}} x^u\ \text dx\\
\end{aligned}
\]
后面积分的原函数一目了然,使用牛顿莱布尼茨公式可以计算出上式,总的复杂度为 \(O(n^4)\)。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#define int long long
using namespace std;
typedef long double ld;
const int N = 250 + 10;
int n, q, p[N], lam[N];
ld f[N][N], T[N], ans[N][N];
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i ++) cin >> T[i] >> lam[i], p[i] = i;
sort(p + 1, p + n + 1, [&](int a, int b) {return T[a] < T[b];});
for(int I = 1; I <= n; I ++) {
memset(f, 0, sizeof f);
f[0][0] = 1;
bool flg = 0;
ld tl = lam[I] * exp(T[I] * lam[I]);
for(int o = 1, cnt = 0, sz = 0; o <= n; o ++) {
int i = p[o];
ld t = exp(T[i] * lam[i]);
if(i == I) flg = 1;
else {
cnt ++;
for(int j = sz; ~j; j --) {
for(int k = o; ~k; k --) {
f[j + lam[i]][k] -= f[j][k] * t;
f[j + lam[i]][k + 1] += f[j][k] * t;
}
}
sz += lam[i];
}
if(flg) {
for(int v = 0; v <= n; v ++) {
for(int j = 0; j <= sz; j ++) {
ans[I][v + n - 1 - cnt] += tl * f[j][v] *
(exp(-T[i] * (j + lam[I])) / (j + lam[I]) - (o == n ? 0 : exp(-T[p[o + 1]] * (j + lam[I])) / (j + lam[I])));
}
}
}
}
}
cin >> q;
while(q --) {
int x, v; cin >> x >> v;
printf("%.6Lf\n", ans[x][v - 1]);
}
return 0;
}

因为不!知道 N01q 模拟。赛怎么:在 T1 卡。一卡选?手,所以T1 放了积!分
浙公网安备 33010602011771号