HDU 3032 (Nim博弈变形) Nim or not Nim?

博弈的题目,打表找规律还是相当有用的一个技巧。

这个游戏在原始的Nim游戏基础上又新加了一个操作,就是游戏者可以将一堆分成两堆。

这个SG函数值是多少并不明显,还是用记忆花搜索的方式打个表,规律就相当显然了。

 1 #include <cstdio>
 2 #include <cstring>
 3
 4 const int maxn = 100;
 5 int sg[maxn * 2];
 6 bool vis[maxn * 2];
 7
 8 int mex(int v)
 9 {
10     if(sg[v] != -1) return sg[v];
11     memset(vis, false, sizeof(vis));
12     for(int i = 0; i < v; i++) vis[mex(i)] = true;
13     for(int i = 1; v - i >= i; i++) vis[mex(i) ^ mex(v - i)] = true;
14     for(int i = 0; ; i++) if(!vis[i]) { sg[v] = i; return i; }
15 }
16
17 int main()
18 {
19     memset(sg, -1, sizeof(sg));
20     sg[0] = 0;
21     for(int i = 0; i < maxn; i++)
22         printf("%d %d\n", i, mex(i));
23
24     return 0;
25 }

打表

 1 #include <cstdio>
 2
 3 inline long long SG(long long x)
 4 {
 5     if(x == 0) return 0;
 6     if(x % 4 == 3) return x + 1;
 7     if(x % 4 == 0) return x - 1;
 8     return x;
 9 }
10
11 int main()
12 {
13     //freopen("in.txt", "r", stdin);
14
15     int T; scanf("%d", &T);
16     while(T--)
17     {
18         int n; scanf("%d", &n);
19         long long ans = 0, x;
20         for(int i = 0; i < n; i++)
21         {
22             scanf("%lld", &x);
23             ans ^= SG(x);
24         }
25         printf("%s\n", ans ? "Alice" : "Bob");
26     }
27
28     return 0;
29 }

代码君

时间: 2024-08-28 23:23:47

HDU 3032 (Nim博弈变形) Nim or not Nim?的相关文章

hdu 3032(博弈sg函数)

题意:与原来基本的尼姆博弈不同的是,可以将一堆石子分成两堆石子也算一步操作,其它的都是一样的. 分析:由于石子的堆数和每一堆石子的数量都很大,所以肯定不能用搜索去求sg函数,现在我们只能通过找规律的办法求得sg的规律. 通过打表找规律可以得到如下规律:if(x%4==0) sg[x]=x-1; if(x%4==1||x%4==2) sg[x]=x; if(x%4==3) sg[x] = x+1. 打表代码: #include<iostream> #include<cstdio> #

HDU 1907 Nim博弈变形

1.HDU 1907 2.题意:n堆糖,两人轮流,每次从任意一堆中至少取一个,最后取光者输. 3.总结:有点变形的Nim,还是不太明白,盗用一下学长的分析吧 传送门 分析:经典的Nim博弈的一点变形.设糖果数为1的叫孤独堆,糖果数大于1的叫充裕堆,设状态S0:a1^a2^..an!=0&&充裕堆=0,则先手必败(奇数个为1的堆,先手必败).S1:充裕堆=1,则先手必胜(若剩下的n-1个孤独堆个数为奇数个,那么将那个充裕堆全部拿掉,否则将那个充裕堆拿得只剩一个,这样的话先手必胜).T0:a1

poj3480 John (nim博弈变形--SJ定理)

John Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2940   Accepted: 1432 Description Little John is playing very funny game with his younger brother. There is one big box filled with M&Ms of different colors. At first John has to eat s

hdu 1730 Northcott Game (nim博弈变形)

# include <algorithm> # include <stdio.h> # include <string.h> # include <math.h> # include <iostream> using namespace std; int main() { int n,m,i,a,b,cot; while(~scanf("%d%d",&n,&m)) { cot=0; for(i=0; i<

HDU 2897 bash 博弈变形

一堆石子N个 每个人最少取P个 最多取Q个 最后取光的人输 问谁赢 X=N%(P+Q)  X=0则先手取Q个必胜 X<=P则后手胜 X>P则先手取P个必胜 #include <iostream> #include <cstdio> #include <string> #include <cstring> using namespace std; int main() { int n, p, q; while ( scanf ( "%d%

Nowcoder 挑战赛23 B 游戏 ( NIM博弈、SG函数打表 )

题目链接 题意 : 中文题.点链接 分析 : 前置技能是 SG 函数.NIM博弈变形 每次可取石子是约数的情况下.那么就要打出 SG 函数 才可以去通过异或操作判断一个局面的胜负 打 SG 函数的时候.由于 N 很大 所以不能使用递归的方式打表.会爆栈 还有要预处理每个数的约数 打出 SG 函数之后 暴力判断初始局面的每堆石子取走约数后是否对答案产生贡献 #include<bits/stdc++.h> #define LL long long #define ULL unsigned long

HDU 3032 Nim or not Nim? (博弈之求SG函数)

题意:经典Nim博弈游戏变换,给你n堆石子pi,每堆有pi个石子, Alice和Bob轮流取石子,每次可以从任意一堆中拿走任意个石子,也可以将某一堆石子分成两个小堆 (每堆石子个数必须不能为0),先拿完者获胜 思路:求SG函数后找规律: SG函数定义及求法:点击打开链接 #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #in

HDU 3032 Nim or not Nim?(sg函数博弈)

题目地址:HDU 3032 这题是很好用来练习sg函数打表的一题. 下面是sg函数值打表代码: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include &

HDU 1850 Being a Good Boy in Spring Festival (Nim游戏变形)

题意:经典Nim游戏博弈,给你n堆牌,每堆a[i]张,每次能从一堆中取出任一张(不能为0),最后不能取者为输 问先手有几种取法保证他最后能获胜. 思路:让Nim_sum=0(a[1]^a[2]----^a[n]=0)时则输,利用这个定理,对于第i堆a[i],除了第i堆,其它的 Nim_sum=k,如果a[i]>k,则先手从第i堆可以取a[i]-k张牌,让a[i]=k,最后a[i]^k==0. #include<cstdio> #include<stdlib.h> #inclu