[SDUSTOJ 1450]捡石子游戏

本文探讨了如何运用斐波那契数列策略来解决SDUSTOJ中的1450题捡石子游戏,通过数列的特性优化游戏策略。

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

//捡石子如果不是Nim就是一般的找规律,简单一些的手撕即可,但是有些,比如这个,就需要先手撕,然后打个表看看规律了。一般都不会很难

#include <cstdio>
#include <cstring>

const int MAX = 100;
int a[MAX][MAX];	//a[i][j]默认为0,表示如果有i个石子Alice第一次取j个为输,a[i][j]=1则表示第一次取j个可以必胜 

int main() {
	memset(a, 0, sizeof(a));
	a[4][1] = 1;
	a[6][1] = 1;
	a[7][2] = 1;//先手撕出前7个的规律
	 
	//然后打表看剩下的 
	for (int i = 8; i < MAX; ++i) {
		//比如有i个,我们知道如果第一次拿了超过i/3向上取整个,那么Bob肯定可以直接拿完,所以只考虑少于i/3向上取整个的 
		for (int j = 1; 3*j < i; ++j) {
			//Alice拿j个,剩下i-j个 
			bool ok = false;	//标记是否是一个必胜的策略
			for (int k = 1; k <= 2*j; ++k) {
				//Alice拿了j个,Bob可以拿[1,2*j]个
				//我们知道,此时就相当于Bob是先手拿k个,如果a[i-j][k]为1,表示对i-j个石子拿掉k个可以保证自己赢 
				if (a[i-j][k]) {
					ok = true;//说明Bob可以达到这个"必胜态" 
					break;
				}
			}
			if (!ok) a[i][j] = 1;//如果Bob经过上面从1到2*j的尝试都无法找到一个必胜的策略,说明Bob是必败的,也就说明Alice必胜了 
		}
	}
	for (int i = 1; i < MAX; ++i) {
		for (int j = 1; j < MAX; ++j) {
			a[i][0] += a[i][j]; 
		}
		if (a[i][0] != 0) printf("%d\n", i);	//看一下哪些是Alice的"必败"态 
	}
	//可以发现,Alice的必败态是一个斐波那契数列 
	return 0;
}

然后就可以搞一个斐波那契数列了。

#include <cstdio>
#include <map>
using namespace std;

int main() {
	map<int, bool> hs;	//map标记一下 
	int a = 1, b = 2, c = 3;
	hs[a] = hs[b] = true;
	//这里利用整数的自然溢出的特点来处理循环终点,当然可以直接用long long代替 
	while (c > 0) {
		hs[c] = true;
		a = b;
		b = c;
		c += a;
	}
	
	int T, n;
	scanf(" %d", &T);
	while (T--) {
		scanf(" %d", &n);
		puts(hs.count(n) ? "Alice!" : "Bob!");	//http://www.cplusplus.com/reference/map/map/count/ 用find也可 
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值