题目:
http://acm.nyist.net/JudgeOnline/problem.php?pid=1077
描述
Yougth和Hrdv这对黄金博弈搭档又要玩游戏了,有n个石子,每次最多可以取a个,最少可以取b个,当剩下少于b的话就要一次性取完,Yougth先取,谁先面对石子为0的局面则赢,他们都非常聪明这是大家都知道的,现在问你谁能赢?
-
输入
-
多组数据,每组三个数n,a,b。
(0<=n<=10^120,其他均int范围内)
输出
- 输出赢了的人的名字。 样例输入
-
7 4 2 6 4 2
样例输出
-
Hrdv Yougth
分析:
博弈有如下原则:
1. 如果一个状态可以有一种方式转化为必败态(交给对手一种必败局面),那么该状态为:必胜态
2. 如果一个状态的所有转移状态皆为必胜态(即无论如何对手拿到的都是必胜的局面),那么改状态为:必败态
根据上面的准则进行递推,可得:
n | 胜负状态(必胜态:1, 必败态:0) |
0 | 1 |
[1, b] | 0 |
[b+1, a+b] | 1 |
[a+b+1, a+2b] | 0 |
[a+2b+1, 2a+2b] | 1 |
... | ... |
我们会发现:[k(a+b)+1, k(a+b)+b] 均为必败态, 即n%(a+b)落在[1, b]区间的都为必败态
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; char n[130]; typedef long long LL; LL f(char* s, int len, LL mod) { LL ret = 0; for(int i=0; i<len; i++) { ret = (ret*10LL + s[i]-'0')%mod; } return ret; } int main () { int len; LL a, b, ans; while(scanf("%s%lld%lld", n, &a, &b) != EOF) { len = strlen(n); ans = f(n, len, a+b); if(ans >=1 && ans <= b) printf("Hrdv\n"); else printf("Yougth\n"); } return 0; }