D1. RPD and Rap Sheet (Easy Version)

题目链接:https://codeforces.com/contest/1543/problem/D1

题意:

交互题,猜密码,设当前的密码为 \(x\) (不知道是多少)(保证初始密码在 0~n-1 之间),每次输入一个数 \(y\) 表示你猜的密码,若猜错,则密码变为 \(z,z\) 满足\({x}{\oplus_k}{z}=y\),我们将 \({\oplus_k}\) 定义为:\(a{\oplus_k}b=a\) 的 k 进制表示下的每一位与 \(b\) 的 k 进制下的对应位做模 k 加法之后得到的 k 进制数。

\(t\) 组测试样例,每组样例首先给定 \(n,k\) ,即你有 \(n\) 次猜密码的机会,每次猜错后密码 \(x\) 会变为 \(z,{x}{\oplus_k}{z}=y\)\(y\) 为你当前猜的密码。每次输出一个数来猜密码,若猜对则裁判程序会输入 1,然后直接进入下一组测试样例,若猜错则裁判程序会输入 0,继续猜直到猜对或达到次数限制。对于每组测试样例,若你都能在给定的 \(n\) 次次数限制内猜对密码,则通过。

本题为简单版本,k 只会为 2。

思路:

k 为 2,\({\oplus_2}\) 即为两个数二进制下的每一位进行模二加法,易验证模二加法和模二减法等价的,且它们等价于异或运算,因此当猜一个数 \(y\),若猜错,密码变为 \(z\)\(x{\oplus_2}z=x\oplus{z}=x\^{}z=y \rightarrow x\^{}z\^{}x=y\^{}x \rightarrow z=y\^{}x=x\^{}y\),因此我们就得到了每一轮猜错后下一轮的密码即为当前密码异或我们猜的密码之后的结果。

由于两次异或同一个数可以抵消,因此我们容易想到枚举 i=0~n-1,每次异或上一个数,由于密码也异或了上一个数,因此若 x=i 则可以猜中,若没有猜中,在本轮结束后,密码异或当前数后也可以把上一轮的异或抵消,相当于是 x 只异或了当前数 i,之后以此类推,可以在最多 n 轮之内猜到密码。
于是可以按照这个顺序来猜密码:

轮数 1 2 3 4 ... n
密码 x x^0 x^1 x^2 ... x^(n-2)
猜的密码 0 1^0 2^1 3^2 ... (n-1)^(n-2)

代码:

#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    ll t;
    cin >> t;
    int n, k, r;
    while (t--)
    {

        cin >> n >> k;
        cout << 0 << endl;
        cin >> r;
        int ans = 1;
        while (r == 0)
        {
            cout << (ans ^ (ans - 1)) << endl;
            cin >> r;
            ans++;
        }
        if (r == 1)
            continue;
    }
}

总结:

posted @ 2021-07-09 11:22  Wajor  阅读(118)  评论(0)    收藏  举报