Description
Alice and Bob are always playing all kinds of Nim games and Alice always goes first. Here is the rule of Nim game:
There are some distinct heaps of stones. On each turn, two players should remove at least one stone from just one heap. Two player will remove stone one after another. The player who remove the last stone of the last heap will win.
Alice always wins and Bob is very unhappy. So he decides to make a game which Alice will never win. He begins a game called “Triple Nim”, which is the Nim game with three heaps of stones. He’s good at Nim game but bad as math. With exactly N stones, how many ways can he finish his target? Both Alice and Bob will play optimally.
Input
Multiple test cases. The first line contains an integer T (T <= 100000), indicating the number of test case. Each case contains one line, an integer N (3 <= N <= 1000000000) indicating the number of stones Bob have.
Output
One line per case. The number of ways Bob can make Alice never win.
Sample
Input
3
3
6
14
Output
0
1
4
Hint
In the third case, Bob can make three heaps (1,6,7), (2,5,7), (3,4,7) or (3,5,6).
题意:就是给你n个石子, 让你分成三堆,怎么让才能先手获胜。哦,对了,他们必须从一堆石头中取出至少一块石头。两个玩家将一个接一个地移动石头。移除最后一堆石头的玩家将获胜。
觉得一下解释很好。摘自:2016山东省第七届ACM省赛
这道题目就是一道尼姆博弈的题目,先来讲下尼姆博弈,其实很简单,有n堆石子,如果n堆石子的异或和是0,则先手必败,否则先手胜。尼姆博弈是利用二进制的思想,那么本题也可以利用二进制的思想,可知,如果要使得Alice输并且Alice为先手,只需要使得三堆石子异或等于0 即可,首先共有n个石子,把n转化成二进制来表示,假设其中有k个1存在,如果要使得三堆石子异或为0,则在三堆石子数的二进制数的每位上1的个数都要是偶数位,又可知,在二进制中,高位的1是由低位进位而得到的,也就是说高位的1可以分解成两个低位的1,当n是奇数的时候,最低位为1且没有办法分解,所以输出0,所以当n为偶数的时候,就有(3^k - 3)/6个,减去3是去掉一个为0的情况,除6是应为本题求得是排列。。。
似乎,已经得出了递推公式了,,,,再次膜一下把尼姆和二进制异或联系起来的脑洞dalao,
//#include<bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include<algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <string>
#include <math.h>
using namespace std;
typedef long long ll;
#define MAXN 45
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
int main()
{
int t;
cin >> t;
for(int i=0; i<t; ++i)
{
ll n;
cin >> n;
if(n%2)
puts("0");
else
{
int ans=0;
while(n)
{
if(n%2)
ans++;
n/=2;
}
cout << (ll)(pow(3, ans)-3)/6 << '\n';
}
}
return 0;
}
我发一下总结吧!无论有没有人看。我记得我前天才写了一篇有关尼姆博弈的博客: 尼姆博弈之 POJ-2975-Nim
然后,我们今天模拟赛就出了一道尼姆博弈的变形题,怪就怪自己 太懒了,看完尼姆的题解后没有深入研究,导致今天这一题没有A出来,感觉很不应该,挺菜的,拖累了队友,垫底了。