题解:P11050 [IOI 2024] 消息篡改者
更好的阅读体验
这题,牛大了!
省略一些和正解无关的部分分做法。
由于 B 不知道串
我们参照 [JOIST 2023] 最后之战 / The Last Battle,如果 B 知道了哪几个格子被 ban 掉了,那么剩下的格子都能用来传输信息。
容易计算我们可以操控的字符数量是
接下来是非人类部分。我们巧妙地想到,可以对于每个能被 A 利用的列,计算出它的后继
至于如何标记
然而由于交互库会篡改一些东西,B 在解码的时候可能会得到一些错误的
如果不想写一些很复杂的找环,就直接找一个起点,跳
最后 B 按照 A 填写
那么这道题就做完了。次数卡的非常满。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
vector<bool> send_packet(vector<bool>);
void send_message(vector<bool>,vector<bool>);
vector<bool> receive_message(vector<vector<bool>>);
void send_message(vector<bool> M,vector<bool> C)
{
M.push_back(0);
while(M.size()<1025)M.push_back(1);
int now=0;
vector<vector<bool> > vec(66);
for(int i=0;i<66;i++)vec[i].resize(31);
for(int i=0;i<31;i++)if(!C[i])
{
int j=(i+1)%31,step=1;
for(;C[j];j=(j+1)%31,step++);
for(int k=0;k<step-1;k++)vec[k][i]=1;
vec[step-1][i]=0;
for(int k=step;k<66;k++)vec[k][i]=M[now++];
}
for(int i=0;i<66;i++)send_packet(vec[i]);
}
vector<bool> receive_message(vector<vector<bool> > R)
{
vector<bool> ans,C(31);
for(int i=0;i<31;i++)C[i]=1;
vector<int> nxt(31);
for(int i=0;i<31;i++)
{
int j=0; for(;j<66&&R[j][i];j++);
nxt[i]=(i+j+1)%31;
}
for(int i=0;i<31;i++)
{
set<int> s; int now=i;
for(int j=0;j<16;j++)
s.insert(now),now=nxt[now];
if(now==i&&s.size()==16) {for(int j:s)C[j]=0; break;}
}
for(int i=0;i<31;i++)if(!C[i])
{
int j=(i+1)%31,step=1;
for(;C[j];j=(j+1)%31,step++);
for(int k=step;k<66;k++)ans.push_back(R[k][i]);
}
while(*ans.rbegin())ans.pop_back();
ans.pop_back();
return ans;
}
How zak's mind works?