题解 猜数
萌新刚学概率.jpg
一个行之有效的乱搞是在一棵 \(k\) 叉树上轮流问该去哪个叶子,问到问出来为止
\(k\) 取 \(3.95\) 时最优,可以拿到 \(64\ \tt pts\)
然后正解:
没什么再复读一遍的意义,所以
假如我现在问了一个区间,它返回 0
那么对于每个区间,答案在这个区间中的概率是怎么变化的呢?
不**知道。题解没写。过了的人每个写的都不一样。
若操作了区间 \(i\),操作前对每个区间维护的概率是 \(p_i\),且返回了 0
已知
- \(p_i\gets p_i\times 0.2\),然后再 \(\forall i, p_i=\frac{p_i}{\sum p}\)
- \(p'_i\gets p_i\times 0.5\)(???),然后再 \(\forall j\neq i, p_j=\frac{1-\frac{p_i}{2}}{1-p_i}\)
- \(p_i\gets p_i\times 0.2\),然后 \(\forall j\),将 \(p_j\) 等比例扩大使 \(\sum p=1\)
都可以过。
没人给出有意义的解释。
我爬了。
upd:战神神给出了一个合理的解释!
假如本次询问了区间 \(i\),\(q=0.8\)
\(B_i\) 为事件「答案在区间 \(i\) 中」
\(A\) 为事件「询问了区间 \(i\) 并返回 \(0\)」
那么 \(P(A|B_i)=1-q\),即表述了「答案在区间 \(i\) 且返回 \(0\) 的概率」
\(P(A|B_{j\neq i})=1\),即表述了「答案不在这个区间且返回 \(0\) 的概率」
然后套贝叶斯公式:
\[\displaystyle P(B_i|A)=\frac{P(B_i)P(A|B_i)}{\displaystyle \sum_{j=1}^n P(B_j)P(A|B_j)}
\]
即可得到
\[P(B_i|A)=\frac{(1-q)p_i}{1-qp_i}
\]
点击查看代码
#include "guess.h"
#include <bits/stdc++.h>
using namespace std;
#define fir first
#define sec second
#define pb push_back
#define ll long long
#define int128 __int128
#define ull unsigned long long
bool Query(vector<pair<ull, ull>> a);
namespace task1{
vector<pair<ull, ull>> s;
ull Guess() {
random_device seed;
mt19937 rand(seed());
s.clear(); s.pb({10, 18446744073709551606llu});
while (s[0].fir!=s[0].sec) {
// cerr<<"once: "<<endl;
pair<ull, ull> all=s.back(); s.pop_back();
ull len=max((ull)((all.sec-all.fir+1)/3.95), 1llu);
// cerr<<"all: ("<<all.fir<<','<<all.sec<<")"<<endl;
for (ull l=all.fir,r; l<=all.sec; l=r+1) {
r=min((int128)l+len-1, (int128)all.sec);
s.pb({l, r});
}
shuffle(s.begin(), s.end(), rand);
// cerr<<"s: "; for (auto it:s) cerr<<"("<<it.fir<<','<<it.sec<<") "; cerr<<endl;
while (1) for (auto& it:s) if (Query({it})) {s.clear(); s.pb(it); goto jump;}
jump: ;
}
return s[0].fir;
}
}
namespace task{
const double k=0.41, eps=1e-3;
vector<pair<double, pair<ull, ull>>> s;
ull Guess() {
random_device seed;
mt19937 rand(seed());
ull all=18446744073709551597llu;
s.clear(); s.pb({1.0, {10, 18446744073709551606llu}});
while (s.size()>1 || s[0].sec.fir!=s[0].sec.sec) {
// shuffle(s.begin(), s.end(), rand);
sort(s.begin(), s.end());
// double sum=0;
// cout<<"s: "; for (auto it:s) cout<<"("<<it.fir<<",("<<it.sec.fir<<','<<it.sec.sec<<")) "; cout<<endl;
// for (auto it:s) sum+=it.fir;
// cerr<<"sum: "<<sum<<endl;
pair<double, pair<ull, ull>> tem=s.back(); s.pop_back();
if (tem.fir>k) {
// cerr<<"pos1"<<endl;
if (rand()&1) {
ull len=tem.sec.sec-tem.sec.fir+1, now=max((ull)(k/tem.fir*len), 1llu);
// cerr<<"len: "<<len<<' '<<now<<endl;
if (now!=len) s.pb({tem.fir*(len-now)/len, {tem.sec.fir+now, tem.sec.sec}});
if (Query({{tem.sec.fir, tem.sec.fir+now-1}})) {s.clear(); s.pb({1, {tem.sec.fir, tem.sec.fir+now-1}}); all=now;}
else {
// cerr<<"s2: "; for (auto it:s) cerr<<"("<<it.fir<<",("<<it.sec.fir<<','<<it.sec.sec<<")) "; cerr<<endl;
// cerr<<"fir: "<<tem.fir<<' '<<tem.fir*now/len<<endl;
s.pb({tem.fir*now/len*0.2, {tem.sec.fir, tem.sec.fir+now-1}});
double sum=0;
for (auto& it:s) sum+=it.fir;
for (auto& it:s) it.fir/=sum;
}
}
else {
ull len=tem.sec.sec-tem.sec.fir+1, now=max((ull)(k/tem.fir*len), 1llu);
// cerr<<"len: "<<len<<' '<<now<<endl;
if (now!=len) s.pb({tem.fir*(len-now)/len, {tem.sec.fir, tem.sec.sec-now}});
if (Query({{tem.sec.sec-now+1, tem.sec.sec}})) {s.clear(); s.pb({1, {tem.sec.sec-now+1, tem.sec.sec}}); all=now;}
else {
// cerr<<"s2: "; for (auto it:s) cerr<<"("<<it.fir<<",("<<it.sec.fir<<','<<it.sec.sec<<")) "; cerr<<endl;
// cerr<<"fir: "<<tem.fir<<' '<<tem.fir*now/len<<endl;
s.pb({tem.fir*now/len*0.2, {tem.sec.sec-now+1, tem.sec.sec}});
double sum=0;
for (auto& it:s) sum+=it.fir;
for (auto& it:s) it.fir/=sum;
}
}
}
else {
// cerr<<"pos2"<<endl;
double pro=tem.fir;
vector<pair<double, pair<ull, ull>>> t; t.pb(tem);
while (pro<k && s.size()) {
// cout<<"while"<<endl;
pair<double, pair<ull, ull>> it=s.back(); s.pop_back();
if (it.fir<k-pro) pro+=it.fir, t.pb(it);
else {
if (rand()&1) {
ull len=it.sec.sec-it.sec.fir+1, now=max((ull)((k-pro)/it.fir*len), 1llu);
if (now!=len) s.pb({it.fir*(len-now)/len, {it.sec.fir+now, it.sec.sec}});
pro+=it.fir*now/len; t.pb({it.fir*now/len, {it.sec.fir, it.sec.fir+now-1}});
}
else {
ull len=it.sec.sec-it.sec.fir+1, now=max((ull)((k-pro)/it.fir*len), 1llu);
if (now!=len) s.pb({it.fir*(len-now)/len, {it.sec.fir, it.sec.sec-now}});
pro+=it.fir*now/len; t.pb({it.fir*now/len, {it.sec.sec-now+1, it.sec.sec}});
}
}
}
vector<pair<ull, ull>> que;
for (auto& it:t) que.pb(it.sec);
// cout<<"query: "; for (auto it:que) cout<<"("<<it.fir<<','<<it.sec<<") "; cout<<endl;
if (Query(que)) {
double sum=0; all=0; s.clear();
for (auto& it:t) sum+=it.fir, all+=it.sec.sec-it.sec.fir+1;
for (auto& it:t) s.pb({it.fir/sum, it.sec});
}
else {
for (auto& it:t) s.pb({it.fir*0.2, it.sec});
double sum=0;
for (auto& it:s) sum+=it.fir;
for (auto& it:s) it.fir/=sum;
}
}
}
return s[0].sec.fir;
}
}
ull Guess() {return task::Guess();}