kmjp's blog

競技プログラミング参加記です

yukicoder : No.3120 Lower Nim

なるほど。
https://yukicoder.me/problems/no/3120

問題

Nimの変形ゲームのinteractive問題である。
2手目以降は、直前の相手の手番で選んだ値以下の値しか選べない、という条件を加えたうえでNimに勝利せよ。

解法

山の石の数のxorが0か非0かで勝者が確定するのは、普通のNimと同じ。
xorが0であった状態で相手がK減らすことを選択した場合、数列中にLSB(K)のbitが立っている山が1つはあることになるので、自分の手番でLSB(K)を減らすことができる。
よってxorが0の状態で後手を取れれば後手必勝。

int N;
int A[10101];

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>N;
	int nim=0;
	FOR(i,N) {
		cin>>A[i];
		nim^=A[i];
	}
	int K=1<<20;
	if(nim) {
		cout<<"First"<<endl;
		while(1) {
			
			nim=0;
			FOR(i,N) nim^=A[i];
			x=1;
			FOR(j,100) if(nim&(1<<j)) {
				x=1<<j;
				break;
			}
				
			y=0;
			FOR(i,N) if(A[i]>=A[y]) y=i;
			cout<<y+1<<" "<<x<<endl;
			A[y]-=x;
			
			
			cin>>x;
			if(x) return;
			
			cin>>x>>y;
			A[x-1]-=y;
			cin>>x;
			if(x) return;
		}
	}
	else {
		cout<<"Second"<<endl;
		while(1) {
			cin>>x>>y;
			A[x-1]-=y;
			cin>>x;
			if(x) return;
			
			nim=0;
			FOR(i,N) nim^=A[i];
			x=1;
			FOR(j,100) if(nim&(1<<j)) {
				x=1<<j;
				break;
			}
				
			y=0;
			FOR(i,N) if(A[i]>=A[y]) y=i;
			cout<<y+1<<" "<<x<<endl;
			A[y]-=x;
			cin>>x;
			if(x) return;
			
		}
	}
}

まとめ

シンプルな問題設定で良い感じ。