Problem:
Problem C: Last One

Problem

あなたは、集合好きな友人Aと一風変わったゲームをしてみる事にした。

n個の要素からなる重複が許される非負の整数の集合Sが与えられる。集合Sに含まれる各要素は非負のpi進数である。集合Sに対して
以下のStep1~3を1つのターンとして、あなたと相手の二人が交互にターンを繰り返す。各ターンではこの番号の順に操作を行う。

Step 1: 集合Sに含まれる全ての要素を一度取り除き、その取り除いた各要素を2進数に変換して、0を消して1が1つ以上連続する部分に分割し、その分割された部分を全て集合Sに加える。

Step 2: このとき集合Sが空になっていたならば、現在このターンをプレイしているプレイヤーは負ける。

Step 3: 集合Sに含まれる要素aを1つ選び、そのaから 1 ≤ x ≤ a を満たす任意の整数xを引く。

下の図は次の入力が与えられたときの最初の1ターンの進行の仕方のうちの1つの例である。

4
10 3
2 11
16 5
16 AE

最初はあなたのターンだ。与えられた入力に対して両者が最善を尽くすとき、果たしてあなたに勝ち目はあるのだろうか。

Input

入力は次の形式で与えられる。

n
p1 m1
p2 m2
...
pi mi
...
pn mn

集合の要素であるpi進数miがn個与えられる。集合の要素の数nは105を超えない。また、2≦pi≦62を満たす。
pi進数miは通常の数字である0~9に加え、アルファベット52文字を使用する。
その順番は012...789ABC...XYZabc...xyzを昇順とし、i番目までの文字を使うものとする。また、pi進数miは10進数で218-1を超えない.

Output

与えられた入力に対しあなたが勝てるならwin、負けるならloseを出力せよ。

Sample Input 1

1
10 1

Sample Output 1

win

Sample Input 2

2
10 1
10 1

Sample Output 2

lose

Sample Input 3

3
25 53AI
43 3BI0
62 pn6

Sample Output 3

win

Solution in C++ (judge verdict: Accepted)

#include <iostream>
#include <cstring>
using namespace std;

typedef long long ll;

string a;
ll ra[128];

void init(){
  a = "";
  for(int i = 0; i < 10; i++){
    a += (char)('0' + i);
    ra['0' + i] = a.size() - 1;
  }
  for(int i = 0; i < 26; i++){
    a += (char)('A' + i);
    ra['A' + i] = a.size() - 1;
  }
  for(int i = 0; i < 26; i++){
    a += (char)('a' + i);
    ra['a' + i] = a.size() - 1;
  }
}

ll toLL(ll p, string m){
  ll res = 0;
  for(int i = 0; i < m.size(); i++){
    res *= p;
    res += ra[m[i]];
  }
  return res;
}

void nim(ll x, ll &calc){
  string tmp;

  for(ll i = 0; (1LL << i) <= x; i++){
    if(x & (1LL << i)){
      tmp += "1";
    }
    else{
      tmp += "0";
    }
  }

  for(ll i = 0; i < tmp.size(); i++){
    if(tmp[i] == '0') continue;

    ll j;
    for(j = i; j < tmp.size() && tmp[j] == '1'; j++);

    calc ^= j - i;
    i = j;
  }
}

int main(){
  init();

  int n;

  while(cin >> n){
    ll calc = 0;

    for(int i = 0; i < n; i++){
      ll p;
      string m;
      cin >> p >> m;

      ll x = toLL(p, m);
      nim(x, calc);
    }

    cout << (0 < calc ? "win" : "lose") << endl;
  }
}