题目描述
牛牛和羊羊都很喜欢青草。今天他们决定玩青草游戏。
最初有一个装有n份青草的箱子,牛牛和羊羊依次进行,牛牛先开始。在每个回合中,每个玩家必须吃一些箱子中的青草,所吃的青草份数必须是4的x次幂,比如1,4,16,64等等。不能在箱子中吃到有效份数青草的玩家落败。假定牛牛和羊羊都是按照最佳方法进行游戏,请输出胜利者的名字。
输入描述
输入包括t+1行。
第一行包括一个整数t(1 ≤ t ≤ 100),表示情况数.
接下来t行每行一个n(1 ≤ n ≤ 10^9),表示青草份数
输出描述
对于每一个n,如果牛牛胜利输出"niu",如果羊羊胜利输出"yang"。
示例1
输入:
3
1
2
3输出:
niu
yang
niu
算法分析
方案一:DFS暴力枚举情况求解(超时)
方案二:暴力DFS找规律,发现每5个niu yang niu niu yang一个周期
DFS找规律:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
// 先手胜利
vector<bool> win(1024, false);
vector<bool> visit(1024, false);
int dfs(int n)
{
if (visit[n])
return win[n];
int eat_grass = 1;
while (eat_grass < n) eat_grass <<= 2;
if (eat_grass == n) {
visit[n] = true;
win[n] = true;
return win[n];
}
// 先手有一种情况胜利,都算胜利(因为一定会采取对自己有利的方法)
for (eat_grass >>= 2; eat_grass >= 1; eat_grass >>= 2) {
//当前n份草,先手吃掉eat_grass后, 后手变成先手, 结果为!win(n-eat_grass)
if (!dfs(n - eat_grass)) {
visit[n] = true;
win[n] = true;
return win[n];
}
}
// 反手胜利
visit[n] = true;
win[n] = false;
return win[n];
}
int main()
{
visit[1] = true;
win[1] = true;
dfs(50);
for (int i = 1; i <= 50; ++i)
cout << win[i] << endl;
return 0;
}
提交代码:
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
int main() {
int t;
cin >> t;
while(t-- > 0) {
int n;
cin >> n;
if(n % 5 == 0 || n % 5 == 2)
cout << "yang" << endl;
else
cout << "niu" << endl;
}
return 0;
}