详细资料参见博弈论入门
hdu 1846 巴什博弈,只要n%(m + 1)==0肯定输。
#include <cstdio>
int main(){
int T ;
int n ;
int m ;
//freopen("hdu1846.in" ,"r" , stdin) ;
scanf("%d" , &T) ;
for( ; T-- ; ){
scanf("%d%d" , &n , &m) ;
puts(n%(m+1) ? "first" : "second") ;
}
return 0;
}
hdu 1847 推一下就可以得到结果了。当然也可以用SG函数去求解。
#include<cstdio>
int main(){
int n ;
while(scanf("%d" , &n)!=EOF){
puts(n%3 ? "Kiki" : "Cici") ;
}
return 0 ;
}
hdu 1848 直接写SG函数,然后就是异或判断就行了。
#include <cstdio>
#include <cstring>
#define maxn 1010
int sg[maxn] ;
int fib[maxn] ;
bool mex[maxn] ;
int top ;
void get_Fib(){
fib[0] = 1 ;
fib[1] = 1 ;
for(int i = 2 ; i < maxn ; i ++){
fib[i] = fib[i - 1] + fib[i - 2] ;
if(fib[i] >= 1000){
top = i ;
break ;
}
}
}
void get_sg(){
sg[0] = 0 ;
for(int i = 1 ; i <= 1000 ; i ++){
memset(mex , 0 , sizeof(mex)) ;
for(int j = 1 ; j <= top ; j ++){
if(i < fib[j])
break ;
mex[ sg[i - fib[j]] ] = 1 ;
}
int j = 0 ;
while(mex[j++]) ;
sg[i] = --j ;
}
}
int main(){
int m , n , p ;
//freopen("hdu1848.in" ,"r" , stdin) ;
get_Fib() ;
get_sg() ;
while(scanf("%d%d%d" , &n , &m , &p) , n||m||p){
puts((sg[n]^sg[m]^sg[p]) ? "Fibo" : "Nacci" ) ;
}
return 0 ;
}
hdu 1849
Nim的变形。
#include <cstdio>
int main(){
int m ;
while(scanf("%d" , &m) , m){
int ans = 0 ;
int p ;
for(int i = 0 ; i < m ; i ++){
scanf("%d" , &p) ;
ans = ans^p ;
}
puts(ans ? "Rabbit Win!" : "Grass Win!") ;
}
return 0 ;
}
hdu 1850 Nim的变形,输出有多少中情况的。先将全部的数异或,然后将异或的结果与第i堆数量进行异或,如果得到的结果小于该堆的数量,则有一种方案。具体的推理很简单,仔细想一下就知道了。
#include <cstdio>
#define maxn 100
int num[maxn] ;
int main(){
int n ;
int nimSum = 0 ;
freopen("hdu1850.in" , "r" , stdin) ;
while(scanf("%d" , &n) , n){
nimSum = 0 ;
for(int i = 1 ; i <= n ; i ++){
scanf("%d" , &num[i]) ;
nimSum ^= num[i] ;
}
int ans = 0 ;
for(int i = 1 ; i <= n ; i ++){
if((nimSum ^ num[i]) < num[i]){
ans ++ ;
}
}
printf("%d\n" , ans) ;
}
return 0 ;
}
hdu 2149 又是一道巴什博弈,只不过这次要输出第一次可以出哪些值。直接上代码吧,
#include <cstdio>
int main(){
int n , m ;
for( ; scanf("%d%d" , &m , &n)!=EOF ;){
if(m%(n+1) == 0){
puts("none") ;
continue ;
}
if(m/(n + 1)){
printf("%d\n" , m%(n + 1)) ;
}
else{
for( ; m <= n ; m ++){
printf("%d" , m) ;
if(m != n)
printf(" ") ;
}
printf("\n") ;
}
}
}
hdu 2188 巴什博弈
#include <cstdio>
int main(){
int T ;
int n , m ;
scanf("%d" , &T) ;
while(T--){
scanf("%d%d" , &n , &m) ;
puts((n%(m + 1)) ? "Grass" :"Rabbit" ) ;
}
return 0 ;
}
hdu 1079 直接用SG函数,或者推一下规律。
#include <cstdio>
int main(){
int y , m , d ;
int T ;
scanf("%d" , &T) ;
while(scanf("%d%d%d" , &y , &m , &d) , T--){
if( (m + d)%2 == 0 || ( d == 30 && (m == 11 || m == 9) ) )
puts("YES") ;
else
puts("NO") ;
}
return 0 ;
}
hdu 1517 找规律,或者SG函数
#include<stdio.h>
int main()
{
double n;
while(scanf("%lf",&n)!=EOF)
{
while(n>18)n/=18;
if(n<=9) printf("Stan wins.\n");
else printf("Ollie wins.\n");
}
return 0;
}
hdu 1404 按照给定的过程模拟一下,计算出每个点的SG值
/*
* 模拟 + sg函数
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
const int maxn = 1000000 ;
char str[10] ;
int sg[maxn + 1] ;
void init(){
memset(sg , 0 , sizeof(sg)) ;
int val ;
int len ;
char curr ;
char j ;
char t[10];
int tmp ;
for(int i = 1 ; i <= maxn ; i ++){
val = 1 ;
itoa(i , str , sizeof(str)) ;
len = strlen(str) ;
for(int k = 0 ; k < len && val ; k ++){
curr = str[k] ;
j = '0' ;
if( !k )
j ++ ;
if(curr == '0'){
for(j = 0 ; j < k ; j ++)
t[j] = str[j] ;
t[k] = '\0' ;
tmp = atoi(t) ;
val = sg[tmp] ;
}
else{
for( ; j < curr && val ; j ++){
str[k] = j ;
tmp = atoi(str) ;
val = sg[tmp] ;
}
}
str[k] = curr ;
}
sg[i] = !val ;
}
}
int main(){
init() ;
int p ;
int sign ;
while(scanf("%s" , str) !=EOF ){
sign = 1 ;
if(str[0] != '0'){
p = atoi(str) ;
sign = sg[p] ;
}
if(sign)
puts("Yes") ;
else
puts("No") ;
}
return 0 ;
}
hdu 1536 SG函数,跟斐波那契那道差不过的题目。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define maxn 105
int si[maxn] ;
int sg[maxn * 100] ;
bool mex[maxn * 100] ;
int m ;
int n ;
int cmp(const void * a , const void * b){
int *aa = (int *)a ;
int *bb = (int *)b ;
return *aa - *bb ;
}
void predour_sg(){
memset(sg , -1 , sizeof(sg)) ;
sg[0] = 0 ;
for(int i = 1 ; i <= 10000 ; i ++){
memset(mex , 0 , sizeof(mex)) ;
for(int j = 0 ; j < m ; j ++){
if(i - si[j] < 0)
break ;
mex[ sg[ i - si[j] ] ] = 1 ;
}
int k = 0 ;
while(mex[k ++]) ;
sg[i] = --k ;
}
}
int main(){
//freopen("1536.in" ,"r" , stdin) ;
while(scanf("%d" , &m) , m){
for(int i = 0 ; i < m ; i ++){
scanf("%d" , &si[i]) ;
}
qsort(si , m , sizeof(si[0]) , cmp) ;
predour_sg() ;
scanf("%d" , &n) ;
while(n--){
int k ;
int x ;
int ans = 0 ;
scanf("%d" , &k) ;
while(k --){
scanf("%d" , &x) ;
ans = ans ^ sg[x] ;
}
if(ans)
putchar('W') ;
else
putchar('L') ;
}
putchar('\n') ;
}
return 0 ;
}