日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

SG函数入门

發(fā)布時(shí)間:2023/12/10 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SG函数入门 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考博客:https://baike.baidu.com/item/SG%E5%87%BD%E6%95%B0/1004609

https://www.cnblogs.com/ECJTUACM-873284962/p/6921829.html

主要參考百度百科:

首先定義mex(minimal excludant)運(yùn)算,這是施加于一個(gè)集合的運(yùn)算,表示最小的不屬于這個(gè)集合的非負(fù)整數(shù)。例如mex{0,1,2,4}=3、mex{1,3,5}=0、mex{}=0。

對(duì)于任意狀態(tài) x , 定義 SG(x) = mex(S),其中 S 是 x 后繼狀態(tài)的SG函數(shù)值集合。如 x 有三個(gè)后繼狀態(tài)分別為?SG(a),SG(b),SG(c),那么SG(x) = mex{SG(a),SG(b),SG(c)}。?這樣 集合S 的終態(tài)必然是空集,所以SG函數(shù)的終態(tài)為 SG(x) = 0,當(dāng)且僅當(dāng) x 為必?cái)↑c(diǎn)P時(shí)。

SG函數(shù)的性質(zhì):

首先,所有的terminal position(目標(biāo)位置)所對(duì)應(yīng)的頂點(diǎn),也就是沒有出邊的頂點(diǎn),其SG值為0,因?yàn)樗暮罄^集合是空集。然后對(duì)于一個(gè)g(x)=0的頂點(diǎn)x,它的所有前驅(qū)y都滿足 g(y)!=0。對(duì)于一個(gè)g(x)!=0的頂點(diǎn),必定存在一個(gè)后繼y滿足g(y)=0

表明,頂點(diǎn)x所代表的postion(位置)是P-position(必?cái)↑c(diǎn))當(dāng)且僅當(dāng)g(x)=0

?

SG值的意義

1,當(dāng)g(x)=k時(shí),表明對(duì)于任意一個(gè)0<=i<k,都存在x的一個(gè)后繼y滿足g(y)=i。為什么一定存在呢?

?因?yàn)閙ex函數(shù)運(yùn)算時(shí),g(y)等于最小的不屬于(y后繼狀態(tài))這個(gè)集合的非負(fù)整數(shù),換言之,y的后繼狀態(tài)一定有 [0,k-1] 這個(gè)范圍才會(huì)出現(xiàn)g(x)=k,k為不小于后繼狀態(tài)(集合),因?yàn)楹瘮?shù)g就是按照mex運(yùn)算得來(lái)的。

2,當(dāng)某枚棋子的SG值是k時(shí),我們可以把它變成0、變成1、……、變成k-1,但絕對(duì)不能保持k不變。這個(gè)聯(lián)想到Nim游戲, Nim游戲的規(guī)則就是:每次選擇一堆數(shù)量為k的石子,可以把它變成0、變成1、……、變成k-1,但絕對(duì)不能保持k不變。這表明,如果將n枚棋子所在的頂 點(diǎn)的SG值看作n堆相應(yīng)數(shù)量的石子,那么這個(gè)Nim游戲的每個(gè)必勝策略都對(duì)應(yīng)于原來(lái)這n枚棋子的必勝策略!

3,對(duì)于n個(gè)棋子,設(shè)它們對(duì)應(yīng)的頂點(diǎn)的SG值分別為(a1,a2,…,an),再設(shè)局面(a1,a2,…,an)時(shí)的Nim游戲的一種必勝策略是把a(bǔ)i 變成k,那么原游戲的一種必勝策略就是把第i枚棋子移動(dòng)到一個(gè)SG值為k的頂點(diǎn)。這就相當(dāng)于可以看做,每次最聰明的操作是按照Nim游戲SG(N)值來(lái)移動(dòng),例如我們想把SG(N)變?yōu)?span style="color:#f33b45;">SG(小于N),就滿足最聰明移動(dòng),但我們真正移動(dòng)的又不是SG(N)的值,移動(dòng)的是原來(lái)頂點(diǎn)N的值,咦,好像也是哦,沒關(guān)系,我們依舊移頂點(diǎn)N的值,只是說(shuō)移動(dòng)頂點(diǎn)N的值時(shí),要滿足移動(dòng)后頂點(diǎn)(小于N),SG(小于N)的值是我們想要的最聰明的SG值。 ? ? ? ?

? ? ? ? ? ? ?

這就好像我們敲代碼,我們通過(guò)高級(jí)程序語(yǔ)言來(lái)間接寫機(jī)器語(yǔ)言運(yùn)行計(jì)算機(jī)。

?

計(jì)算1~n的SG函數(shù)值步驟如下:

1、使用 數(shù)組f可改變當(dāng)前狀態(tài) 的方式記錄下來(lái)。

2、然后我們使用 另一個(gè)數(shù)組 將當(dāng)前狀態(tài)x 的后繼狀態(tài)標(biāo)記。

3、最后模擬mex運(yùn)算,也就是我們?cè)跇?biāo)記值中 搜索 未被標(biāo)記值 的最小值,將其賦值給SG(x)。

4、我們不斷的重復(fù) 2 - 3 的步驟,就完成了 計(jì)算1~n 的函數(shù)值

代碼:

//f[N]:可改變當(dāng)前狀態(tài)的方式,N為方式的種類,f[N]要在getSG之前先預(yù)處理 //SG[]:0~n的SG函數(shù)值 //S[]:為x后繼狀態(tài)的集合 int f[N],SG[MAXN],S[MAXN]; void getSG(int n){int i,j;memset(SG,0,sizeof(SG));//因?yàn)镾G[0]始終等于0,所以i從1開始for(i = 1; i <= n; i++){//每一次都要將上一狀態(tài) 的 后繼集合 重置memset(S,0,sizeof(S));for(j = 0; f[j] <= i && j <= N; j++)S[SG[i-f[j]]] = 1; //將后繼狀態(tài)的SG函數(shù)值進(jìn)行標(biāo)記for(j = 0;; j++) if(!S[j]){ //查詢當(dāng)前后繼狀態(tài)SG值中最小的非零值SG[i] = j;break;}} }

?

給出一道入門級(jí)的題目

hdu 1848

#include <cstdio> #include<algorithm> #include<cstring> using namespace std; const int MAXN=1010; #define N 20 int f[N],SG[MAXN],S[MAXN];///f[]可走步數(shù)//S[]后繼存在狀態(tài) void getSG(int n){int i,j;memset(SG,0,sizeof(SG));///PN點(diǎn)for(i = 1; i <= n; i++){///從i=1開始memset(S,0,sizeof(S));///每次初始化S[]后繼存在狀態(tài)for(j = 0; f[j] <= i && j < N; j++)///f[i]<i;S[SG[i-f[j]]] = 1;///f[]可走步數(shù)///S[]后繼存在狀態(tài)for(j = 0;;j++) if(!S[j]){///找出后繼存在狀態(tài)中的最小非負(fù)整數(shù);SG[i] = j;?///最終得出該點(diǎn)i的SG值break;}} } int main(){int n,m,k;f[0] = f[1] = 1;for(int i = 2; i <= 16; i++)///由題意得初始化可走步數(shù)(可取個(gè)數(shù))f[i] = f[i-1] + f[i-2];getSG(1000);///得出所有點(diǎn)的SG函數(shù)值while(scanf("%d%d%d",&m,&n,&k),m||n||k){if(SG[n]^SG[m]^SG[k]) printf("Fibo\n");else printf("Nacci\n");}return 0; }

?

?

我的標(biāo)簽:做個(gè)有情懷的程序員。

?

?

?

總結(jié)

以上是生活随笔為你收集整理的SG函数入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。