Codeforces.835E.The penguin's game(交互 按位统计 二分)

题目链接

\(Description\)

  有一个长为\(n\)的序列,其中有两个元素为\(y\),其余全为\(x\)。你可以进行\(19\)次询问,每次询问你给出一个下标集合,交互库会返回这些元素的异或和。给定\(n,x,y\),你需要求出两个\(y\)的下标。
  \(n\leq 1000,1\leq x,y\leq 10^9\)。

\(Solution\)

  对连续区间询问得到的结果只有那么几种,可以直接判断\(y\)的个数的奇偶性。但是区分不出来该区间有0个还是2个\(y\)。
  两个\(y\)的下标不同。我们可以借此对下标某一位是\(0/1\)计算其异或和,若不同,则两个\(y\)的下标在这一位上不同。最后我们能得到两个\(y\)下标的异或和。
  找一个\(y\)在某位不同且元素个数最少的位置,在较小的集合内(大小\(\leq\frac{n}{2}\))二分,这里面只有一个\(y\),就可以得到它的位置,异或之前的和就得到另一个。次数正好\(19\)。
  当然也可以不二分。任找该位不同的一位\(p\),然后枚举不等于\(p\)的每位,我们要判断是否有一个\(y\)(另一个可以直接通过之前在该位的询问得到)在该位上是\(1\)。只枚举\(p,i\)位为1的下标,可以保证只有一个\(y\)并判断出这个\(y\)是否在这位上是\(1\),因为询问可以确定其中是否有\(y\)。

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=1005;

int n,x,y;
bool vis[N];

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
inline bool Query()
{
    int t=0, res;
    for(int i=1; i<=n; ++i) if(vis[i]) ++t;
    if(!t) return 0;
    printf("? %d",t);
    for(int i=1; i<=n; ++i) if(vis[i]) printf(" %d",i);
    putchar('\n'); fflush(stdout);
    return res=read(),(t&1&&!(res^y))||(!(t&1)&&res^y==x);//想错好多次。。
}

int main()
{
    n=read(), x=read(), y=read();
    int sum=0, p=0;
    for(int i=0; 1<<i<=n; ++i)
    {
        for(int j=1; j<=n; ++j) if(j>>i&1) vis[j]=1;
        if(Query()) sum|=1<<i, p=i;
        for(int j=1; j<=n; ++j) vis[j]=0;
    }
    int p1=0, p2=1<<p;
    for(int i=0; 1<<i<=n; ++i)
        if(i!=p)
        {
            for(int j=1; j<=n; ++j) if(j>>i&1 && j>>p&1) vis[j]=1;
            p2|=Query()<<i;
            for(int j=1; j<=n; ++j) vis[j]=0;
        }
    if((p1=p2^sum)>p2) std::swap(p1,p2);
    printf("! %d %d\n",p1,p2); fflush(stdout);

    return 0;
}

Codeforces.835E.The penguin's game(交互 按位统计 二分)

原文地址:https://www.cnblogs.com/SovietPower/p/9546002.html

时间: 2024-10-09 01:31:15

Codeforces.835E.The penguin's game(交互 按位统计 二分)的相关文章

Codeforces 835E The penguin&#39;s game

Pay attention: this problem is interactive. Penguin Xoriy came up with a new game recently. He has n icicles numbered from 1 to n. Each icicle has a temperature — an integer from 1 to 109. Exactly two of these icicles are special: their temperature i

Codeforces Round #626 D. Present 异或按位确定 +二分or双指针

Codeforces Round #626 D. Present 异或按位确定 +二分or双指针 题意 给n个数,求他们两两的和的异或结果 n(4e5) 值域(1e7) 思路 异或问题一般都是按位确定,那么怎么确定第k位的值呢.首先第k位的值只和[1,k]位有关系,也就是说只跟a[i]本来在这一位有的数和进位有关系.那么怎么处理和的问题呢.首先我们只考虑[1..k]位,那么他们的和记为sum,如果sum在第k位有值 那么sum的值为 \(2^k+x\)因为只考虑[1..k]位所以a的最大值为\(

Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market 二分答案 +排序

Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market 二分答案 +排序 题意 有 a[ i ] 个数 要求选最多的数 使其和不超过 S ,且在此情况下,和最小选最多数情况下 和最小 且 每个数有加成 如果选了 k个数 那么加成后 就是 a[ i ] + k*i ; 题解 二分mid 表示选了个数 加成一下,将加成以后结果排序一下 , 若前 mid数 和大于 s 则此方案不可行 PS 要用 long long ..... 还有 co

codeforces 679A Bear and Prime 100 交互

第一次交互题,记录一下吧 #include <cstdio> #include <iostream> #include <ctime> #include <vector> #include <cmath> #include <map> #include <queue> #include <algorithm> #include <cstring> using namespace std; typed

Codeforces 862D. Mahmoud and Ehab and the binary string 【二分】(交互题)

<题目链接> 题目大意: 有一个长度为n(n<1000)的01串,该串中至少有一个0和一个1,现在由你构造出一些01串,进行询问,然后系统会给出你构造的串与原串的   Hamming distance ,现在要求你按照步骤进行交互式操作,最终得到任意一个0.1的下标. 解题分析:因为原串中至少存在一个0和一个1,所以一定存在一个01或者10序列,因此我们可以用二分来寻找这个序列(注意二分过程中选择区间的操作).二分之后,一定能够得到01或10序列,然后将其按先0后1的顺序输出即可. 1

Codeforces Round #361 (Div. 2) D. Friends and Subsequences RMQ+二分

题目链接 http://codeforces.com/problemset/problem/689/D 代码 1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 6 const int maxn = 200000 + 10; 7 int n, a[maxn], b[maxn]; 8 int d_min[maxn][30]; 9 int d_max[m

【AcWing 113】【交互】特殊排序——二分

(题面来自AcWing) 有N个元素,编号1.2..N,每一对元素之间的大小关系是确定的,关系不具有传递性. 也就是说,元素的大小关系是N个点与N*(N-1)/2条有向边构成的任意有向图. 然而,这是一道交互式试题,这些关系不能一次性得知,你必须通过不超过10000次提问来获取信息,每次提问只能了解某两个元素之间的关系. 现在请你把这N个元素排成一行,使得每个元素都小于右边与它相邻的元素. 你可以通过我们预设的bool函数compare来获得两个元素之间的大小关系. 例如,编号为a和b的两个元素

Codeforces Round #626 Div2 D. Present(位掩码,二分)

题目链接:https://codeforces.com/contest/1323/problem/D 题意:给了大小为4e5的数组a,其中1<=ai<=1e7.求所有点对和的异或和,即: 思路: 按位来考虑,因为两个元素的和<=2e7,而2e7小于225,因此结果最多是25位.我们考虑答案中每一位ans[k]的值(0<=k<=24). 显然,ai中仅有0-k位会对第k位有影响,因此对数组a全部对2k+1取模,得到数组b,对b按升序排序. 这样,0<=bi<=2k+

Codeforces #291 (Div. 2) D. R2D2 and Droid Army(RMQ+二分)

题意: 有n*m的矩阵,然后你有k发子弹.现在你可以朝着任意列发射子弹,每一发子弹都会使该列上的数值-1,最小减少到0. 现在问你连续最长的行数,在k发子弹内,使得这些行上的数值全部为0. 思路: 简单的二分枚举最长行数区间,每个区间的最大值决定了要发射的子弹数,所以是RMQ问题,当然这里的枚举全部枚举,用尺取法也可以. //889 ms #include<cstdio> #include<algorithm> #include<cstring> #include<