1. 程式人生 > 其它 >CF835E The penguin's game 題解

CF835E The penguin's game 題解

link

Solution

同一型別的套路題見了這麼多了結果還是做不出來,我麻了。

可以發現我們可以枚舉出哪些二進位制位這兩個位置不一樣,然後我們求出一種一個位置另外一個就可以直接通過異或求出。考慮怎麼求出一個,首先我們肯定可以劃分出兩個集合使得二者不在同一個集合裡面,然後我們直接遞迴即可。

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN

//char buf[1<<21],*p1=buf,*p2=buf;
//#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int n,x,y;

#define poly vector<int>
int getval (poly S){
	cout << "? " << S.size() << " ";
	for (Int x : S) cout << x << " ";
	int v;cin >> v;
	return v;
}

int Solve (poly S){//找到S集合中y的位置 
	if (S.size() == 1) return S[0];
	vector <int> T0,T1;int siz = S.size() >> 1;
	for (Int i = 0;i < siz;++ i) T0.push_back (S[i]);
	for (Int i = siz;i < S.size();++ i) T1.push_back (S[i]);
	int tmp = getval (T0);
	if ((siz & 1) && tmp == y) return Solve (T0);
	else if (!(siz & 1) && tmp == (x ^ y)) return Solve (T0);
	else return Solve (T1);
}

signed main(){
	read (n,x,y);int det = 0;
	for (Int i = 0;(1 << i) <= n;++ i){
		vector <int> S;
		for (Int k = 1;k <= n;++ k) if (!(k >> i & 1)) S.push_back (k);
		int tmp = getval (S);
		if ((S.size() & 1) && tmp == y) det |= (1 << i);
		else if (!(S.size() & 1) && tmp == (x ^ y)) det |= (1 << i);
	}
	for (Int i = 0;(1 << i) <= n;++ i) if (det >> i & 1){
		vector <int> S;
		for (Int k = 1;k <= n;++ k) if (!(k >> i & 1)) S.push_back (k);
		int pos = Solve (S),ano = pos ^ det;if (pos > ano) swap (pos,ano);
		cout << "! " << pos << " " << ano << endl;
		return 0; 
	}
	return 0;
}