SG函数模板(转)
sg[i]为0表示i节点先手必败。
首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。
例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。
对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Grundy函数g如下:g(x)=mex{ g(y) | y是x的后继 },这里的g(x)即sg[x]
例如:取石子问题,有1堆n个的石子,每次只能取{1,3,4}个石子,先取完石子者胜利,那么各个数的SG值为多少?
sg[0]=0,f[]={1,3,4},
x=1时,可以取走1-f{1}个石子,剩余{0}个,mex{sg[0]}={0},故sg[1]=1;
x=2时,可以取走2-f{1}个石子,剩余{1}个,mex{sg[1]}={1},故sg[2]=0;
x=3时,可以取走3-f{1,3}个石子,剩余{2,0}个,mex{sg[2],sg[0]}={0,0},故sg[3]=1;
x=4时,可以取走4-f{1,3,4}个石子,剩余{3,1,0}个,mex{sg[3],sg[1],sg[0]}={1,1,0},故sg[4]=2;
x=5时,可以取走5-f{1,3,4}个石子,剩余{4,2,1}个,mex{sg[4],sg[2],sg[1]}={2,0,1},故sg[5]=3;
以此类推.....
x 0 1 2 3 4 5 6 7 8....
sg[x] 0 1 0 1 2 3 2 0 1....
计算从1-n范围内的sg值,
s[]存储可以走的步数,s[0]表示可以有多少种走法
s[]需要从小到大排序
1.可选步数为1~m的连续整数,直接取模即可,sg[x] = x % (m+1);
2.可选步数为任意步,sg[x] = x;
3.可选步数为一系列不连续的数,用sg函数计算
模板1(dfs):
/*
s数组表示合法移动集合,从小到大排序。sNum合法移动个数
sg数组初始化为-1,对每个集合s仅需初始化1次
*/
const int MAXN = ;//s集合大小
const int MAXM = + ;//
int s[MAXN], sNum;
int sg[MAXM]; int dfsSg(int x)
{
if (sg[x] != -) {
return sg[x];
}
int i;
bool vis[MAXN];//sg值小于等于合法移动个数sNum memset(vis, false, sizeof(vis));
for (i = ; i < sNum && s[i] <= x; ++i) {
dfsSg(x - s[i]);
vis[sg[x - s[i]]] = true;
}
for (i = ; i <= sNum; ++i) {
if (!vis[i]) {
sg[x] = i;
break;
}
}
return sg[x];
}
模板2(打表):
求出所有sg值,有时没必要,用dfs就行
/*
s数组表示合法移动集合,从小到大排序。sNum合法移动个数
sg值对每个集合s仅需求一次
*/
const int MAXN = ;//s集合大小
const int MAXM = + ;//
int s[MAXN], sNum;
int sg[MAXM];
bool exist[MAXN];//sg值小于等于合法移动个数sNum void getSg(int n)
{
int i, j;
sg[] = ;//必败态
for (i = ; i <= n; ++i) {
memset(exist, false, sizeof(exist));
for (j = ; j < sNum && s[j] <= i; ++j) {
exist[sg[i - s[j]]] = true;
}
for (j = ; j <= sNum; ++j) {
if (!exist[j]) {
sg[i] = j;
break;
}
}
}
}
hdu 1848 Fibonacci again and again(sg)
取石子问题,一共有3堆石子,每次只能取斐波那契数个石子,先取完石子者胜利,问先手胜还是后手胜
#include <bits/stdc++.h>
using namespace std; /*
s数组表示合法移动集合,从小到大排序。sNum合法移动个数
sg数组初始化为-1,对每个集合s仅需初始化1次
*/
const int MAXN = ;//s集合大小
const int MAXM = + ;//
int s[MAXN], sNum;
int sg[MAXM]; int dfsSg(int x)
{
if (sg[x] != -) {
return sg[x];
}
int i;
bool vis[MAXN];//sg值小于等于合法移动个数sNum memset(vis, false, sizeof(vis));
for (i = ; i < sNum && s[i] <= x; ++i) {
dfsSg(x - s[i]);
vis[sg[x - s[i]]] = true;
}
for (i = ; i <= sNum; ++i) {
if (!vis[i]) {
sg[x] = i;
break;
}
}
return sg[x];
} int main()
{
int i;
s[] = ;
s[] = ;
for (i = ; i < MAXN; ++i) {
s[i] = s[i - ] + s[i - ];
//printf("%d %d\n", i, s[i]);
}
sNum = ;
int m, n, p;
int sum;
memset(sg, -, sizeof(sg));
while (~scanf("%d%d%d", &m, &n, &p)) {
if (m == && n == && p == ) {
break;
}
dfsSg(m);
dfsSg(n);
dfsSg(p);
sum = sg[m] ^ sg[n] ^ sg[p];
if (sum != ) {
printf("Fibo\n");
} else {
printf("Nacci\n");
}
}
return ;
}
#include <bits/stdc++.h>
using namespace std; /*
s数组表示合法移动集合,从小到大排序。sNum合法移动个数
sg值对每个集合s仅需求一次
*/
const int MAXN = ;//s集合大小
const int MAXM = + ;//
int s[MAXN], sNum;
int sg[MAXM];
bool exist[MAXN];//sg值小于等于合法移动个数sNum void getSg(int n)
{
int i, j;
sg[] = ;//必败态
for (i = ; i <= n; ++i) {
memset(exist, false, sizeof(exist));
for (j = ; j < sNum && s[j] <= i; ++j) {
exist[sg[i - s[j]]] = true;
}
for (j = ; j <= sNum; ++j) {
if (!exist[j]) {
sg[i] = j;
break;
}
}
}
} int main()
{
int i;
s[] = ;
s[] = ;
for (i = ; i < MAXN; ++i) {
s[i] = s[i - ] + s[i - ];
//printf("%d %d\n", i, s[i]);
}
sNum = ;
int m, n, p;
int sum;
getSg();
while (~scanf("%d%d%d", &m, &n, &p)) {
if (m == && n == && p == ) {
break;
}
sum = sg[m] ^ sg[n] ^ sg[p];
if (sum != ) {
printf("Fibo\n");
} else {
printf("Nacci\n");
}
}
return ;
}
SG函数模板(转)的更多相关文章
- hdu1536&&hdu3023 SG函数模板及其运用
S-Nim Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u Submit Status ...
- hdu 1536 SG函数模板题
S-Nim Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- 【非原创】sg函数模板
学习博客:戳这里 解题模型: 1.把原游戏分解成多个独立的子游戏,则原游戏的SG函数值是它的所有子游戏的SG函数值的异或. 即sg(G)=sg(G1)^sg(G2)^...^sg(Gn) ...
- Light OJ 1199:Partitioning Game(SG函数模板)
Alice and Bob are playing a strange game. The rules of the game are: 1. Initially there are n p ...
- HDU 1847-Good Luck in CET-4 Everybody!-博弈SG函数模板
Problem Description 大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此.当然,作为在考场浸润了十几载 ...
- SG函数模板
这篇虽然是转载的,但代码和原文还是有出入,我认为我的代码更好些. 转载自:http://www.cnblogs.com/frog112111/p/3199780.html 最新sg模板: //MAXN ...
- hdu 1536 S-Nim(sg函数模板)
转载自:http://blog.csdn.net/sr_19930829/article/details/23446173 解题思路: 这个题折腾了两三天,参考了两个模板,在这之间折腾过来折腾过去,终 ...
- SG函数 模板
int get_SG(int x) { ) return SG[x]; ]={}; ;i<=n;i++) ) v[get_SG(x-s[i])]=; int i; ;v[i];i++); SG[ ...
- SG函数模板(洛谷2197nim游戏
#include <iostream> #include <cstdio> #include <queue> #include <algorithm> ...
随机推荐
- canvas 绘制 矩形 圆形
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <tit ...
- Java中的数组
1,可以创建自己的类的数组,但是自己的类必须实现get()和put函数 2,声明数组:int[] arrayOfInt.注意,定义数组时不可以指定大小 3,创建与初始化:通过new.arrayOfIn ...
- 计算机网络(7)-----TCP协议概述
传输控制协议(Transmission Control Protocol) 概念 一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中,它 ...
- WeX5 快速开发平台 V3.6 正式版发布
WeX5 V3.6 正式版核心特性:一.打包特性增强: 1- 提供多WebView选择,引入腾讯X5引擎,可自动适配移动设备环境进行切换,使通过X5打包生成的App具备更高的兼容性及更小的文件尺寸: ...
- Linq一 基础知识
1.什么是Linq 他是VS2008(.net framework 3.5)之后一项重大的突破 全程Lnaguage Integrated Query,可以成为数据迭代器. 主要有以下5大块组成: L ...
- Ubuntu Command-Line: Enable Unlimited Scrolling in the Terminal
At times when using the terminal, the output from a command can be so long, you simply can’t scroll ...
- PC缺少一个或多个网络协议 qq可登录(win10)
打开适配器连接 1打开网络适配器 2卸载microsoft 3 网络客户端 4重启
- 黑马程序员:Java编程_String
=========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== 描述字符串对象的类是java.lang.String,String类是不可变(f ...
- 2015GitWebRTC编译实录17-audio_processing_neon编译问题解决
编译audio_processing_neon lib时,发现只要涉及到WEBRTC_ARCH_ARM64就会出现问题,仔细回想了下,年初编译旧版本解决arm64支持问题时,好像也是要把这个注掉,但是 ...
- 将war包部署到服务器的详细步骤
第一步: 先将项目打包成war文件,也就是将在项目上单击鼠标右键,选择Export: 选择WAR file,点击下一步: 会出现如下所示,选择你要保存的位置,点击完成: 在你所选择的地方会有个如下所示 ...