難易度評価

難易度を1〜10段階で評価できます。投票はあとから変更・取り消しできます。

難易度(投票) Lv.3.0 (1票)

投票の分布
  1. Lv.10票
  2. Lv.20票
  3. Lv.31票
  4. Lv.40票
  5. Lv.50票
  6. Lv.60票
  7. Lv.70票
  8. Lv.80票
  9. Lv.90票
  10. Lv.100票

難易度の目安を見る ↗

ログインして難易度を投票

外部サイトへ移動します

リンク先の URL を確認してから開いてください。

別タブで開く

Jenga Game

作成者 kammyu

難易度(作成者設定) Lv.4

難易度(投票) Lv.3.0 (1票)

実行時間制限
2 秒
メモリ制限
512 MiB

Nimによる解法

最終盤面に着目すると、必ず SiS_i は {1,3},{2}\{1,3\},\{2\} のいずれかになっていることが分かります。
一つの集合に着目したときに、{1,3}\{1,3\} になる場合は 11 回の操作が、{2}\{2\} になる場合は 22 回の操作が必ず行われます。

これは、次の様に NN 個全ての山が 22 のNimとして考えることができます。

  • 集合 SiS_i から 1,31,3 のいずれかを取り除くとき、山 ii から石を 11 つ取り除く。
  • 集合 SiS_i から 22 を取り除くとき、山 ii から石を 22 つ取り除く。

よって、⨁i=1N2\bigoplus_{i=1}^N2 が 00 であるかどうかを考えればよく、これは NN が奇数の時に 22 、偶数の時に 00 になります。
ここから、奇数の時にAlice、偶数の時にBobが勝つことが分かります。

真似っこ戦法による解法

NN が偶数の時を考えます。
Bobは以下の戦略によって必ず勝つことができます。

Sj={1,2,3}S_j=\{1,2,3\} を満たす jj の個数を aa 、 1∈Sj1\in S_j または 3∈Sj3\in S_j のうち一方のみを満たす jj の個数を bb とします。

ここで、 a,ba,b をどちらも偶数と仮定します。

最初は a=N,b=0a=N,b=0 なので仮定は真です。

Aliceが前のターンで集合 SiS_i から xx を取り除いたとします。

  • x=1,3x=1,3 の場合
    • Si={1,2,3}S_i=\{1,2,3\} の場合
      2≤a2\le a より、Sj={1,2,3}S_j=\{1,2,3\} なる j(≠i)j(\ne i) が存在するので、SjS_j から 1,31,3 のいずれかを取り除きます。
      aa が 22 だけ減り、仮定より a−2a-2 も偶数です。
    • Si≠{1,2,3}S_i\ne\{1,2,3\} の場合
      2≤b2\le b より、同じように 1∈Sj1\in S_j または 3∈Sj3\in S_j のうち一方のみを満たす j(≠i)j(\ne i) が存在するので、SjS_j から 1,31,3 のいずれか存在する方を取り除きます。
      bb が 22 だけ減り、仮定より b−2b-2 も偶数です。
  • x=2x=2 の場合
    2≤a2\le a より、Sj={1,2,3}S_j=\{1,2,3\} なる jj が存在するので、SjS_j から 22 を取り除きます。
    aa が 22 だけ減り、仮定より a−2a-2 も偶数です。

NN が奇数の時は、最初にAliceがいずれかの集合から 22 を取り除くことで NN が偶数の場合に帰着でき、Aliceが必勝となります。

実装例(C++)

#include <bits/stdc++.h>
using namespace std;
int main()
{
  int T;
  cin >> T;
  while (T--)
  {
    int N;
    cin >> N;
    cout << (N % 2 ? "Alice" : "Bob") << endl;
  }
}

ユーザー解説

ユーザー解説を書く

ユーザー解説はまだありません。