//HDU1848,SG函数,简单应用示例
2016-08-28 15:49
316 查看
0
先理解怎么样用!然后再弄明白为什么这样用。
1
首先定义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...
摘自http://blog.csdn.net/lttree/article/details/24886205
2
先理解怎么样用!然后再弄明白为什么这样用。
1
首先定义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...
摘自http://blog.csdn.net/lttree/article/details/24886205
2
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> //HDU1848,SG函数,简单应用示例 using namespace std; int m,n,p; bool bj[1010]; int sg[1010]; int fib[21]; void Get_sg(int t,int x){ memset(sg,0,sizeof(sg)); for(int i=1;i<=x;i++){//sg[0]=0 memset(bj,0,sizeof(bj)); for(int j=1;j<=t&&fib[j]<=i;j++){ bj[sg[i-fib[j]]]=1; } for(int j=0;j<=x;j++){ if(bj[j]==0){ sg[i]=j; break; } } } } int main() { fib[1]=1;fib[2]=2; for(int i=3;i<17;i++){//i==16,fib[i]==1597>1000 fib[i]=fib[i-1]+fib[i-2]; } Get_sg(16,1001); while(~scanf("%d%d%d",&n,&m,&p)&&(n+m+p)){ //Get_sg(max(max(n,m),max(m,p))); 放在外面,Get一次即可 if((sg ^sg[m]^sg[p])==0){///注意,^优先级低于==,所以不加括号则WA cout<<"Nacci"<<endl; } else{ cout<<"Fibo"<<endl; } } }
相关文章推荐
- hdu 1848 Fibonacci again and again(sg函数的简单应用 模板题 )
- hdu 1848【博弈】sg函数应用
- hdu 1848 SG函数应用
- HDU1536,SG函数(①打表,②回溯),简单应用示例2
- HDU_1848 Fibonacci again and again(SG函数应用)
- HDU 1848 Fibonacci again and again(SG函数的应用)
- HDU1536 SG函数的简单应用
- HDU 1848(SG函数应用)
- VS2005 + VSS6.0 简单应用示例
- C# .NET Remoting 简单应用示例
- VS2005 + VSS6.0 简单应用示例
- VS.NET 2005 + VSS6.0简单应用示例
- 简单画图板示例(虚函数应用示例)
- Java+Flex整合应用简单示例 (mx:RemoteObject)
- 创建一个简单的WebPart应用示例
- 简单画图板示例(虚函数应用示例)
- JNDI访问LDAP服务简单应用示例
- javaFx菜单简单应用示例--1多级菜单
- VS2005 + VSS6.0 简单应用示例
- 一个比较容易调用 功能比较完善的 cookie 操作类 附带一些简单的应用示例