P13105 题解
妙妙交互题。
感觉这种题没有什么通用技巧啊,只能依题目而定。
先考虑
看到
想想怎样才能和
考虑这样的事实:
将
于是我们想到:
用二进制给计算机编号,最后把回答的结果整合回十进制,看看少了哪些数,就知道哪些计算机出了故障。
以第一组样例为例,我们将下面的矩阵一行一行地发送给评测机:
0 0 0 0 1
0 0 1 1 0
0 1 0 1 0
这个矩阵是什么意思呢?其实如果你竖着看,就会发现,第
也就是说,第
由于
0 0 1
0 1 0
1 0 0
整合一下,第一列是 0 3。
代码应该很好写,就不给了。
或者直接看后面也行。
考虑如何做
容易观察到
怎么样才能防止浪费呢?
考虑下面的算法:当
为什么这样能减少浪费,且不会产生难以辨别的漏洞呢?因为
这就意味着,只要在整合后我们发现某一列的结果比后一列大,那就可以说明这两列肯定在不同的块内,我们也就可以统计答案了。
具体的,如果我们发现编号
由于我比较懒,所以当
#include <bits/stdc++.h>
using namespace std;
char s[1222][1222];
int flg[1222], z;
signed main() {
int TT;
cin >> TT;
while (TT--) {
memset(flg, 0, sizeof(flg));
int n, b, f;
cin >> n >> b >> f;
if (n > 32) {
for (int i = 1; i <= 5; i++) {
for (int j = 0; j < n; j++)
cout << (((j % 32) >> (5 - i)) & 1);
cout << endl;
for (int j = 1; j <= n - b; j++) cin >> s[j][i];
}
int lst = -1, nct = 0;
for (int i = 1; i <= n - b; i++) {
int x = 0;
for (int j = 1; j <= 5; j++)
x = x * 2 + s[i][j] - 48;
if (x <= lst) {
for (int j = 0; j < 32; j++)
if (!flg[j]) cout << j + 32 * nct << " ";
nct++;
for (int j = 0; j < 32; j++) flg[j] = 0;
}
flg[x] = 1, lst = x;
}
for (int i = 0;i <= (n - 1) % 32;i++)
if (!flg[i]) cout << i + 32 * nct << " ";
} else {
int cnt = 0, tmp = n - 1;
while (tmp) tmp >>= 1, cnt++;
for (int i = 1; i <= cnt; i++) {
for (int j = 0; j < n; j++)
cout << ((j >> (cnt - i)) & 1);
cout << endl;
for (int j = 1; j <= n - b; j++) cin >> s[j][i];
}
for (int i = 1; i <= n - b; i++) {
int x = 0;
for (int j = 1; j <= cnt; j++) x = x * 2 + s[i][j] - 48;
flg[x] = 1;
}
for (int i = 0; i < n; i++)
if (!flg[i]) cout << i << " ";
}
cout << endl;
cin >> z;
}
return 0;
}