HDU 2176 take (m pile) stone game (Nim game + bit operation)

Problem Description
m pile of stones, two people take turns. They can only take stones in one pile. The winner who takes the first wins. The negative output of the winner who takes the first wins is No. for example, the winner who takes the first in 5 piles of 5, 7, 8, 9 and 10 wins. When the winner takes stones for the first time, he can take 7 from the pile with 8 and leave 1, or take 9 from the pile with 9 and leave 0, or take 7 from the pile with 10 and leave 3

Input
Input multiple groups. The first line of each group is m, m < = 200000. The following M non-zero positive integers. m=0 exit

Output
First mover negative output No. first mover wins, outputs Yes, and then outputs all the methods of the first fetch of the first time. If you take several stones from the heap with a stones and leave b, you will win and output a and b. see Sample Output

Sample Input
2
45 45
3
3 6 9
5
5 7 8 9 10
0

Sample Output
No
Yes
9 5
Yes
8 1
9 0
10 3

The stone game is a classic Nim game problem.

There are n piles of stones, and there are ai stones in the i pile. The two players take turns to choose one pile at a time and take away as many stones as they want. You can take away one pile, but you can't take it without taking it. The man who took the last stone won.

There is no draw in the game, only two situations: the first hand must win and the first hand must lose.

For this kind of problem, there is such a theorem: the first hand in NIM game must win if and only if a1 xor a2 xor a3 xor... XOR an= 0
(on the contrary, if and only if a1 xor a2 xor a3 xor... xor an = 0)

xor represents the "xor" in the bit operation. The above formula is the xor sum of the number of stones in each pile.

We don't have to find out why we must find the exclusive or sum of the number of stones for this game. This is just a more appropriate and convenient solution to solve this kind of problem. If we can find other ways, we can also use it.

The proof of this theorem is the key to solve this problem.

Proof: (the proof process refers to the advanced guide of algorithm competition)

First of all, all items are taken as a certain defeat situation (the opponent takes the last one and the opponent wins). At this time, a1 xor a2 xor a3 xor... xor an = 0.

For any situation:

① If a1 xor a2 xor a3 xor... XOR an = x= 0, let x binary represent the k-th bit of the highest 1 under, then there is at least a pile of stones ai (i.e. > = 1 pile), and its k-th bit is 1. Obviously, ai xor x < ai, we take some stones from the ai pile and change them into ai xor x, and we get a situation where the exclusive or sum of the number of stones in each pile is 0 (x xor x = 0).

② If a1 xor a2 xor a3 xor... xor an = 0, no matter how the stones are taken, the exclusive or sum of the number of stones in each pile is obtained= 0 In fact, it can be proved by counter evidence, so I won't repeat it here.

To sum up: (mathematical induction should be used for strict proof)

①a1 xor a2 xor a3 xor … xor an = x != 0 is a winning situation. There must be an action that makes the opponent face a situation where the exclusive or sum of the number of stones in each pile is 0, that is, the opponent loses (A1 XOR A2 XOR A3 XOR... xor an = 0).

② a1 xor a2 xor a3 xor... xor an = 0 is a losing situation. There must be an action to make the opponent face the situation that the sum of the number of stones in each pile is not equal to 0, that is, the opponent wins (a1 xor a2 xor a3 xor... XOR an = x! = 0).

#include<iostream>
#include<sstream>
#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<unordered_set>
#include<map>
#include<unordered_map>
#include<bitset>
#include<utility>
using namespace std;
//---------------------------------------------------------
#define inf 0x3f3f3f3f
const double pi = acos(-1.0);
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
//---------------------------------------------------------
int m;
const int M = 2e5 + 10;
vi a;
int main()
{
	ios_base::sync_with_stdio(false), cin.tie(0);
	while (cin >> m)
	{
		if (!m) break;
		a.clear();
		int res = 0;
		while (m--)
		{
			int x;
			cin >> x;
			res ^= x;
			a.push_back(x);//Storage m Rockfill
		}
		if (!res) cout << "No" << endl;//If the exclusive or sum of m rockfill is 0, the first hand will fail and output No directly
		else//If the XOR sum is not 0, it means that the first hand must win
		{
			cout << "Yes" << endl;
			//Find the k-th bit of the highest 1 under the XOR and res binary representation. Why is this required? There is an explanation below
			int k = 0;
			for (int i = 0; i < 31; ++i)
			{
				if (((res >> i ) & 1) == 1)//The bitwise and operation indicates that the number on the current bit is 1, and res has not changed
				{
					k = i;
				}
			}
			//Since the XOR of m heap of stones and the highest 1 of res are in the k-th position, there is at least one heap of stones ai (i.e. > = 1 heap), and its k-th position is 1.
			//Obviously, ai xor res < ai, we take some stones from the ai pile and change them into ai xor res, and we get a situation where the exclusive or sum of the number of stones in each pile is 0 (res xor res = 0), so that the first hand wins and the second hand loses.
	
			//Now let's find out which of the m heaps of stones has the number of stones (a[i]) with the k-th bit of 1, and output the number of raw stones of these heaps and the remaining number after removing some stones according to the requirements of the topic.
			for (int i = 0; i < a.size(); ++i)
			{
				int tmp1 = a[i];
				int tmp2 = a[i];
				tmp1 >>= k;//Shifting a[i] right by K bits under binary representation is equivalent to dividing 2^k under decimal system
				if ((tmp1 & 1) == 1)//At this time, tmp1 & 1 represents the k-th bit under a[i] binary. Here, judge whether it is 1
				{
					cout << a[i] << ' ';
					tmp2 ^= res;
					cout << tmp2 << endl;
				}
			}
		}
	}
	return 0;
}

Tags: Algorithm

Posted on Thu, 14 Oct 2021 17:11:53 -0400 by mr_armageddon