LOJ3831 「IOI2022」囚徒挑战 题解
题目描述
这是一道交互题。
有两个袋子 \(A\) 和 \(B\) ,装有不同数量的硬币,保证硬币数量 \(\le n\) 。
任意时刻白板上都写有一个数,初始为 \(0\) 。
接下来有若干(不超过 \(n\) )个人,依次进行如下操作:
- 记白板上的数为 \(i\) ,根据
s[i][0]
决策看哪个袋子,记袋中硬币个数为 \(j\) 。 - 指认哪个袋子硬币数量较少,或将白板上的数改为
s[i][j]
。
你的目标是构造 \(x\times(n+1)\) 的二维数组 s[i][j]
,使得这些人能够正确判断出哪个袋子硬币数量较少。
其中 s[i][0]
的值必须为 0
或 1
,分别表示看 \(A\) 或 \(B\) 。
对 \(1\le j\le n\) ,若 s[i][j]
的值为 -1
或 -2
,则分别表示指认 \(A\) 或 \(B\) 数量较少,否则 s[i][j]
应当是一个 \(\le x\) 的非负整数,表示这个人在白板上写下的数。
你需要实现以下函数:
-
vector<vector<int>> devise_strategy(int N);
返回你构造的二维数组。
数据范围
- \(1\le n\le 5000\) 。
- 你可以自行决定 \(x\) 的值,但需要保证 \(x\le 20\) 。
时间限制 \(\texttt{2s}\) ,空间限制 \(\texttt{2048MB}\) 。
分析
记 \(A\) 袋硬币数量为 \(a\) , \(B\) 袋硬币数量为 \(b\) ,目标比较 \(a\) 和 \(b\) 的大小。
考虑二进制拆分,第一个人看 \(a\) 并写下最高位,第二个人看 \(b\) 后将最高位与 \(a\) 比较,如果不同则直接出结果,如果相同则写下次高位。
在构造 s
数组时,每两个人为一组,通过组的编号可以知道当前正在处理哪一位,组内分别处理上一位写下的是 \(0/1\) 的情况。
于是我们得到了一个 \(x=2\lceil\log_2n\rceil=26\) 的做法。如果换成三进制,可以得到 \(x=3\lceil\log_3n\rceil=24\) 。
有一个小优化:由于 \(a\neq b\) ,所以看完最后一位可以直接出结果。 \(x\) 降至 \(2\lceil\log_2n\rceil-2=24\) 。
事实上这个优化还可以推广,假设当前已经确定 \(a,b\in[l,r]\) ,那么如果看到 \(l\) 或 \(r\) 则可以直接出结果。
记 \(f_n\) 表示值域为 \(n\) 时 \(x\) 的最小值。根据上面这个优化,我们可以把原来的转移方程 \(f_n=\min f_{\lceil\frac nk\rceil}+k\) 改成 \(f_n=\min f_{\lceil\frac{n-2}k\rceil}+k\) 。
打表发现刚刚好 \(f_{5000}=20\) ,一条可行的路径(从高到低)为 \(3,3,3,3,2,2,2,2\) 。
递归实现,时间复杂度 \(\mathcal O(nx)\) 。
#include<bits/stdc++.h>
#include"prison.h"
using namespace std;
const int maxn=5005;
int n;
vector<vector<int>> s;
void dfs(int dep,int l,int r,int L,int R,int i,int lim)
{///当前第dep层,保证另一个数属于[l,r],自己属于[L,R],白板上的数为i,已经使用0~lim的编号
if(l>r) return ;
int k=dep<=4?3:2,len=(r-l-1+k-1)/k;
///注意同一个i会被dfs到多次,但是只处理j\in[L,R]的情况
s[i][0]=dep&1?0:1;
for(int j=L;j<=l;j++) s[i][j]=dep&1?-1:-2;
for(int j=r;j<=R;j++) s[i][j]=dep&1?-2:-1;
for(int t=1,x=l+1,y;x<=r-1;t++,x=y+1)
{///第t部分为[x,y]
y=min(x+len-1,r-1);
for(int j=x;j<=y;j++) s[i][j]=lim+t;
dfs(dep+1,x,y,l,r,lim+t,lim+k);
}
}
vector<vector<int>> devise_strategy(int _n)
{
n=_n,s.resize(21);
for(int i=0;i<=20;i++) s[i].resize(n+1);
dfs(1,1,n,1,n,0,0);
return s;
}
本文来自博客园,作者:peiwenjun,转载请注明原文链接:https://www.cnblogs.com/peiwenjun/p/17060751.html