CF744B Hongcow's Game
阿新 • • 發佈:2020-09-16
因為對角線上都是 \(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; }