网上没找到博客orz
补了一下去年南宁没做出来的题… 感觉自己… 离银还有段距离…
(我队友就不一定了
2^r 个人打淘汰赛 有个人的实力是第k名 实力高的人打败实力低的人的概率是p 这个人可以自己安排选手的顺序 问最后这个人获胜的概率是多少
显然 按照 比我强的-比我弱的-我 这样安排顺序,然后从开始的(比我强的-比我弱的)递归往上找,一开始T了, 看知乎上的回答说可以记忆化… 就加了个记忆化过了。转移的时候要按奇偶讨论一下,具体看代码吧
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <map>
using ll = unsigned long long;
using ld = long double;
#define mp std::make_pair
std::map<std::pair<ll, ll>, ld> me;
ll r, k;
ld p, t;
ld gao(ll l, ll r) {
if (me.find(mp(l, r)) != me.end()) return me[mp(l, r)];
if (l == 0) {
t = p*gao(0, r>>1);
me[mp(l, r)] = t;
return t;
}
if (r == 0) {
t = (1.0-p)*gao(l>>1, 0);
me[mp(l, r)] = t;
return t;
}
if (!(l&1)) {
t = p*gao(l>>1, r>>1);
me[mp(l, r)] = t;
return t;
} else {
t = p*(p*gao((l>>1)+1, (r>>1)-1) + (1.0-p)*gao(l>>1, r>>1));
me[mp(l, r)] = t;
return t;
}
}
int main(int argc, char *argv[]) {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int T;
std::cin >> T;
while (T--) {
me.clear();
std::cin >> r >> k >> p;
me[mp(0,1)] = p;
me[mp(1,0)] = (1.0-p);
ll num = 1LL<<r;
ll l = k-1, r = num-k;
if (p < 0.5) {
std::swap(l, r);
}
std::cout << std::fixed << std::setprecision(6) << gao(l, r) << '\n';
}
}