[タイトル] トピックのリンク
二つのプレイヤーが作る.TO(何のお菓子を選んでいないが許可されていない)、nはヒープからキャンディーを選んで、最後の1は、彼らが同じヒープから来キャンディーの任意の数を選ぶことができgame.Onに各ターンを獲得するピックプレイヤーを交代しますそれらのそれぞれがミスをしたことがない場合は、プレイヤーがゲームに勝つかを調べるoperation.Pleaseゲームより面白い、プレイヤーは3つの小さな山(なし空のヒープ)の代わりに、ピッキングに1つのヒープを分離することができます。
InputIntputは、複数のテストケースが含まれています。最初の行は整数 1 ≤ T ≤ 100 1≤T≤100、テストケースの数。各ケースは整数で始まるN、ヒープの数を示し、次の行は、N個の整数含ま S [ 0 ] 、S [ 1 ] 、。。。。、S [ N - 1 ]、S [0]、[1]、...、S [N-1]とヒープ表すだ Sを[ 0 ] 、S [ 1 ] 、。。。、S [ N - 1 ]、S [0]は、[1]〜S、...、S [N-1]それぞれのオブジェクト。(1≤N≤106、1≤ S [ I ] ≤ 10 9 )(1≤n≤106,1≤s[I]≤109)OutputFor各テストケースは、出力「最初のプレイヤーが勝つのいずれかを含むwhickライン。 「または」第二のプレイヤーが「勝利。
サンプル入力
2 2 4 4 3 1 2 4
サンプル出力
第二のプレイヤーが勝ちます。 まずプレイヤーの勝利
を意味[タイトル]
同様のニム(nは石のヒープは、いくつかの山から石を取り除く2テイクターン)は、参加:(あなたが石を奪うことはできませんが、石は3つのグループに分けられ、各杭はできません空に)
正確にすべての石の勝利が完了した後に撮影したものです
[解説]
一般的な石がニムのゲームのn後継状態0〜N-1を重ね、すべての石のスタック数が0であるとの排他的論理和障害状態に運命にあります。
分割操作は、例えば、10から235までの分割は、実際には、後継者に相当2 ^ 3 ^ 4 = 5、後継者に対応する123に7ダウンが状態1 ^ 2 ^ 3 = 7述べ
7後続のすべてを状態^ 1 ^ 51 ^ 2 ^ 41 ^ 3 ^ 32 ^ 2 ^ 3 01234561
なしそれ(SG(X)=後続状態にSG関数の性質を持つテーブルを打ちます最小の自然数)
の観察をすることができる
SG(X-)= X- +。1(X-%==。8. 7)
SG(X-)= 1-X-%==。8(X-0)
SG(X-)= X-他
[SG]定理
Pポイント:失うポイント、限り、他の当事者間違いなく、失うとして、この点に位置プレーヤー
Nポイント:ポイントの勝利を、プレイヤーはこの点の上、限り、彼は間違いを持っていないとして、それは勝たなければならないされ
定理は:
1.すべてのポイントがまとめられていますPがポイントです。
2.関係なく動作、点Pは、勝利ポイントN.に失われる可能性が
3.任意の時点Nから点Pの負けを入力するには、少なくとも一つの方法を獲得します
MEX動作:
まず操作のセットに適用されるMEX(最小excludant)オペレーションを定義し、これは最小値を表す非負の整数の集合に属しません。
すなわち:MEX(S)=分{ X}、x∈N、x∉S
例えばMEX {0,1,2,4} = 3、MEX {2,3,5} = 0、MEX {}は= 0。
SG機能:
定理1:
1.は、図の勝利ゲームに特定の状況がある場合は、ノードに対応する状況のSG関数の値が0より大きいがある場合にのみ。
ノードに対応する状況のSG関数の値がゼロに等しい場合にのみ図2は、ゲーム状況に運命。
定理2:
図構成されるゲームゲーム複数の有向グラフとSGゲーム関数値がゼロでないある場合にのみ場合、勝つ{GiがN}があります。
[コード]プレイテーブル
1 #include <bits/stdc++.h> 2 using namespace std; 3 int g[1010]; 4 void init() { 5 memset(g, -1, sizeof(g)); 6 } 7 int getSG(int x) { 8 if(g[x] != -1) return g[x]; 9 if(x == 0) return 0; 10 if(x == 1) return 1; 11 if(x == 2) return 2; 12 int vis[110]; 13 memset(vis, 0, sizeof(vis)); 14 for(int i = 1; i < x; i++) { 15 int t = 0; 16 int a = getSG(i); 17 vis[a] = 1; 18 for(int j = 1; j < x - i; j++) { 19 int b = getSG(j); 20 int c = getSG(x - i - j); 21 vis[a^b^c] = 1; 22 } 23 } 24 vis[0] = 1; 25 for(int i = 0; ; i++) if(!vis[i]) 26 return g[x] = i; 27 } 28 int main() { 29 int n; 30 init(); 31 for(int i = 1; i <= 100; i++) { 32 g[i] = getSG(i); 33 printf("%d %d %d\n", i, i % 8, g[i]); 34 } 35 }
【AC代码】
1 #include <bits/stdc++.h> 2 using namespace std; 3 int getsg(int x){ 4 if(x%8==0)return x-1; 5 if(x%8==7)return x+1; 6 return x; 7 } 8 int main(){ 9 int t,n,c,ans; 10 scanf("%d",&t); 11 while(t--){ 12 ans=0; 13 scanf("%d",&n); 14 for(int i=1;i<=n;i++){ 15 scanf("%d",&c); 16 ans^=getsg(c); 17 } 18 if(ans)printf("First player wins.\n"); 19 else printf("Second player wins.\n"); 20 } 21 return 0; 22 }