1. 程式人生 > 實用技巧 >CF744B Hongcow's Game

CF744B Hongcow's Game

因為對角線上都是 \(0\),所以如果詢問時包含了對角線,那結果必然是 \(0\),會對判斷造成干擾
因此我們處理詢問的結果時,如果當前這一行的處於對角線上的那一位,在詢問時給出的 \(k\) 個數中,則應該忽略這一行結果(因為它是 \(0\)

所以,就要想辦法讓每一位不在對角線上的數,都在至少一次詢問中,不和它那一行的對角線上的數同時出現
用二進位制的想法考慮,因為任意一位不在對角線上的數,和那一行在對角線上的數的列號,都至少有一個二進位制為相同
所以就列舉每一個二進位制位,分別詢問所有的在這個二進位制位上是 \(0\)\(1\) 的列號
那麼對於每個數,就都會在它和它那一行對角線的列號,的不同的那個二進位制位被列舉時,產生有效的詢問

話說這種思路好像還挺常見的,之前在 bzoj 某圖論題(具體哪個忘了),好像就是用類似於 XX 和 XX 至少一個二進位制位不同,來用二進位制的思路優化的建邊

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<iomanip>
#include<cstring>
#define reg register
#define EN puts("")
inline int read(){
	register int x=0;register int y=1;
	register char c=std::getchar();
	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
	return y?x:-x;
}
int a[1005];
int main(){
	int n=read();
	std::memset(a,0x3f,sizeof a);
	for(reg int cnt,i=0;i<10;i++){
		cnt=0;
		for(reg int j=1;j<=n;j++)if(j&(1<<i)) cnt++;
		if(!cnt) goto NEXT;
		printf("%d\n",cnt);
		for(reg int j=1;j<=n;j++)if(j&(1<<i)) printf("%d ",j);EN;
		std::fflush(stdout);
		for(reg int j=1;j<=n;j++){
			cnt=read();
			if(j&(1<<i)) continue;
			a[j]=std::min(a[j],cnt);
		}
		NEXT:;
		cnt=0;
		for(reg int j=1;j<=n;j++)if(!(j&(1<<i))) cnt++;
		if(!cnt) continue;
		printf("%d\n",cnt);
		for(reg int j=1;j<=n;j++)if(!(j&(1<<i))) printf("%d ",j);EN;
		std::fflush(stdout);
		for(reg int j=1;j<=n;j++){
			cnt=read();
			if(!(j&(1<<i))) continue;
			a[j]=std::min(a[j],cnt);
		}
	}
	puts("-1");
	for(reg int i=1;i<=n;i++) printf("%d ",a[i]);
	std::fflush(stdout);
	return 0;
}