凭直觉做的过了,但是实际上并没有搞清楚为什么是对的。
设了一个数组 E,满足关系 Ek=[k=0]+i∪j=k∑Ei×pj,本题答案为 i=0∑2n−2Ei(E2n−1 必为 ∞,不加上)
这个关系式可以用 FMT 写成 E^=E^⋅P^+1,其中 E^ 表示 E 数组的莫比乌斯变换,P^ 表示 p 数组的莫比乌斯变换,⋅ 表示对应位置直接相乘。
解方程得 E^=1−P^1(除法为对应位置直接相除而不是多项式求逆)。
因此先把 p 做个 FMT,把 E^ 算出来再 IFMT 回去。
但是我其实到现在也没搞明白我设的 E 是个啥。求教。
#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
using namespace std;
typedef long long ll;
const int MAXN = (1 << 20) + 5;
int n, tot;
double p[MAXN], E[MAXN];
void FMT(double a[]) {
rep(i, 0, n)
rep(u, 0, tot)
if (u >> i & 1)
a[u] += a[u ^ (1 << i)];
}
void invFMT(double a[]) {
rep(i, 0, n)
rep(u, 0, tot)
if (u >> i & 1)
a[u] -= a[u ^ (1 << i)];
}
int main() { ios::sync_with_stdio(0); cin.tie(0);
cin >> n, tot = (1 << n) - 1;
rep(u, 0, tot)
cin >> p[u];
FMT(p);
rep(u, 0, tot)
E[u] = 1 / (1 - p[u]);
invFMT(E);
double ans = 0;
rep(u, 0, tot-1)
ans += E[u];
if (isinf(ans))
cout << "INF" << '\n';
else
cout << fixed << setprecision(10) << ans << '\n';
return 0;
}