题解 猜数

传送门

萌新刚学概率.jpg

一个行之有效的乱搞是在一棵 \(k\) 叉树上轮流问该去哪个叶子,问到问出来为止
\(k\)\(3.95\) 时最优,可以拿到 \(64\ \tt pts\)

然后正解:
没什么再复读一遍的意义,所以

image
image
image

假如我现在问了一个区间,它返回 0
那么对于每个区间,答案在这个区间中的概率是怎么变化的呢?
不**知道。题解没写。过了的人每个写的都不一样。
若操作了区间 \(i\),操作前对每个区间维护的概率是 \(p_i\),且返回了 0
已知

  1. \(p_i\gets p_i\times 0.2\),然后再 \(\forall i, p_i=\frac{p_i}{\sum p}\)
  2. \(p'_i\gets p_i\times 0.5\)(???),然后再 \(\forall j\neq i, p_j=\frac{1-\frac{p_i}{2}}{1-p_i}\)
  3. \(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();}
posted @ 2022-06-30 10:34  Administrator-09  阅读(4)  评论(0编辑  收藏  举报