CF15C Industrial Nim (博弈论:nim游戏)

codeforces题目链接: https://codeforces.com/problemset/problem/15/C

CF15C Industrial Nim

题目描述

There are $ n $ stone quarries in Petrograd.

Each quarry owns $ m_{i} $ dumpers ( $ 1<=i<=n $ ). It is known that the first dumper of the $ i $ -th quarry has $ x_{i} $ stones in it, the second dumper has $ x_{i}+1 $ stones in it, the third has $ x_{i}+2 $ , and the $ m_{i} $ -th dumper (the last for the $ i $ -th quarry) has $ x_{i}+m_{i}-1 $ stones in it.

Two oligarchs play a well-known game Nim. Players take turns removing stones from dumpers. On each turn, a player can select any dumper and remove any non-zero amount of stones from it. The player who cannot take a stone loses.

Your task is to find out which oligarch will win, provided that both of them play optimally. The oligarchs asked you not to reveal their names. So, let's call the one who takes the first stone «tolik» and the other one «bolik».

输入格式

The first line of the input contains one integer number $ n $ ( $ 1<=n<=10^{5} $ ) — the amount of quarries. Then there follow $ n $ lines, each of them contains two space-separated integers $ x_{i} $ and $ m_{i} $ ( $ 1<=x_{i},m_{i}<=10^{16} $ ) — the amount of stones in the first dumper of the $ i $ -th quarry and the number of dumpers at the $ i $ -th quarry.

输出格式

Output «tolik» if the oligarch who takes a stone first wins, and «bolik» otherwise.

输入输出样例 #1

输入 #1

2
2 1
3 2

输出 #1

tolik

输入输出样例 #2

输入 #2

4
1 1
1 1
1 1
1 1

输出 #2

bolik

思路:

发现这是nim游戏的简单应用,主要难度在于找出如何简化异或运算,不暴力求解。

这道题目用到的性质是:一个偶数与比它大1的奇数的异或为1
我们先对x判断,如果x为奇数,就先异或x,然后x++,m--;
这样我们就可以方便的以当成x是偶数的情况考虑了
每当ans经过4次异或,这四次异或的值都为0,因为1与1异或为0
后面几种情况就是按照顺序往后思考即可

题解:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
typedef unsigned long long ull;
int n;
ull m,x;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    ull ans=0;
    for(int i=1;i<=n;i++)
    {
        cin>>x>>m;
        if(x%2==1)
        {
            ans^=x;
            x++;
            m--;
        }

        if(m%4==0)ans^=0;
        if(m%4==1)ans^=(x+m-1);
        if(m%4==2)ans^=1;
        if(m%4==3)
        {
            ans^=1;
            ans^=(x+m-1);
        }
        

        // cout<<ans<<endl;
    }
    if(ans==0)cout<<"bolik"<<endl;
    else cout<<"tolik"<<endl;

    return 0;
}
posted @ 2025-05-29 13:34  屈臣  阅读(11)  评论(0)    收藏  举报