2016山东省第七届acm省赛 G题Triple Nim

本文介绍了一种名为TripleNim的游戏,这是一种特殊的Nim游戏变体,涉及将一定数量的石子分成三堆以确定赢家。文章详细解释了游戏规则,并提供了一种计算确保第二位玩家获胜的石子分配方案数量的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Triple Nim

Time Limit: 2000MS Memory limit: 65536K

题目描述

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.

输入

 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.

输出

 One line per case. The number of ways Bob can make Alice never win.

示例输入

3
3
6
14

示例输出

0
1
4

提示

 In the third case, Bob can make three heaps (1,6,7), (2,5,7), (3,4,7) or (3,5,6).

来源

  “浪潮杯”山东省第七届ACM大学生程序设计竞赛

题目链接http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/3566.html

题意很好理解,就是有一堆石子,一共有n个,把n个石子分成三堆,求有多少种分配的方式能够使得bob win?

很容易就能够明白题目是让干什么的,这道题目就是一道尼姆博弈的题目,先来讲下尼姆博弈,其实很简单,有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是应为本题求得是排列。。。


#include <stdio.h>
#include <math.h>

int Binary(int num){
	int cnt = 0;
	while(num){
		if(num % 2)
			cnt ++;
		num /= 2;
	}
	return cnt;
}

int main(){
	int t;
	scanf("%d",&t);
	while(t --){
		int num;
		scanf("%d",&num);
		
		if(num % 2){
			printf("0\n");
			continue;
		}
		
		int ans = Binary(num);
		long long cnt = (pow(3,ans) - 3) / 6;
		printf("%lld\n",cnt);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值