SG博弈題目總集

2021-08-16 14:40:42 字數 3584 閱讀 1782

裸的nim遊戲啦!

#include 

#include

int main()

return

0;}

問有幾種方案讓先手必敗

在證明nim遊戲的sg函式的「根據這個判斷被判為n-position的局面一定可以移動到某個p-position」命題時,有這麼一段證明:對於某個局面(a1,a2,…,an),若a1^a2^…^an不為0,一定存在某個合法的移動,將ai改變成ai』後滿足a1^a2^…^ai』^…^an=0。不妨設a1^a2^…^an=k,則一定存在某個ai,它的二進位制表示在k的最高位上是1(否則k的最高位那個1是怎麼得到的)。這時ai^k

#include 

#include

int a[2000];

int main()

return

0;}

給出n堆石子,兩個人輪流操作

可以 從任意一堆石子中拿出至少乙個石子

或者 將一堆石子分成三份不為0的石子

先打表求出所有的sg值,然後找一下規律

打表程式是關鍵啊!

#include 

#include

#include

#define mem(a,b) memset(a,b,sizeof(a))

const

int maxm=1010;

int sg[maxm],vis[maxm];

inline

void makesg()

}for(int j=0;;j++)

if(!vis[j])

}for(int i=0;i<=100;i++) printf("%d %d %d\n",i,sg[i],i==sg[i]);

}inline

void work()

puts(flag?"first player wins.":"second player wins.");

}int main()

這道題目為上一道題目的簡化版,將變三堆的操作變為變兩堆

#include 

#include

#include

int sg[1010],vis[1010];

inline

void makesg()

for(int j=0;;j++)

if(!vis[j])

}for(int i=0;i<=100;i++) printf("%d %d %d\n",i,sg[i],i==sg[i]);

}inline

void work()

puts(flag?"alice":"bob");

}int main()

有n個位置,每個位置可以單向的去往m個位置,給出q個物品的初始位置

兩個人可以移動k步,不能操作的人輸

用dfs拓展可以去的位置求解sg值

區域性定義陣列要記得初始化(為什麼本地執行沒事啊!!!

#include 

#include

#include

const

int maxm=222000;

int head[maxm],sg[maxm],cnt,n,q;

int net[1000003],to[1000003];

void addedge(int x,int y)

int dfs(int now)

for(int i=0;;i++) if(!vis[i]) return i;

}void work()

while((scanf("%d",&q))&&q)

puts(flag?"win":"lose");

}}int main()

數論+sg函式

對於每個數字,我們可以將其分解成一系列質數的乘積(也就是分解質因數

這樣,每個數字就可以看出質因數個數的堆

那麼sg[x]=質因數個數

套用最簡易的nim遊戲結論即可

使用線性篩,改進一下分解質數的方法,把求出的sg值給存起來

zoj的評測速度感人

#include 

#include

#include

const

int maxm=5000000+1;

int prime[365971],cnt,sg[maxm],a[maxm],n;

bool vis[maxm];

inline

void pre()

}}inline

int getsg(int x)

} if(x>1) k++;

return sg[t]=k;

} inline

void work()

if(!flag) printf("bob\n");

else

} }int main()

return

0;}

給你一段長為n的的線段。

兩個遊戲者輪流在一段長為2,未被染色的線段上塗色。

無法塗色的遊戲者輸

很明顯sg[0]=0,sg[1]=0,sg[2]=1

然後求i的sg,去列舉中間沒染過的線段即可!

#include 

#include

#include

const

int maxm=60;

int sg[maxm],vis[maxm];

inline

void makesg()

}}int main()

puts(flag?"yes":"no");

}return

0;}

題意:兩個人輪流選數,選的數x有以下要求:

①,2<=x<=20

②,已選數的倍數不能選

③,不同已選數的倍數的和不能選

當沒有可以選的數的時候,當前選數的人就算輸。

思路,狀壓+sg函式

zoj不刪除檔案讀入顯示 segmentation fault !

#include 

#include

#include

#define idx(x) (1<<(x-1))

const

int maxm=1

<<19;

int sg[maxm];

int getsg(int s)

}for(int i=0;;i++)

if(!vis[i]) return sg[s]=i;

}int main()

printf("scenario #%d:\n",case);

if(!getsg(sta)) printf("there is no winning move.\n");

else

printf(".\n");

}printf("\n");

}return

0;}

博弈sg函式

sg函式 個人認為還是用於三種方法都無法解決的情況,如按特殊數字取石子 我們把整個博弈過程抽象為有向無環圖 1.幾項準備工作 mex求最小非負整數mex 0,mex 3,mex 0 sg x mex 就是石頭變少的繼 這樣sg就滿足幾個性質 1.sg x 0時,它的後繼都不為零 2.sg x 0時,...

博弈SG函式

題意 乙個棋盤有n行,每行20格仔,都有一些棋子,兩個人輪流進行這個操作 選擇某一行乙個棋子移動到該行右邊第乙個空的格仔。不能進行的人輸。問先手是否能贏。分析 sg函式的應用,當時自己做的時候沒做出來qaq。終結點是這一行沒有棋子可以走,即0,然後逆推出其他結點的sg函式。每一行的狀態看成是乙個結點...

博弈 SG函式和SG定理

在介紹sg函式和sg定理之前我們先介紹介紹必勝點與必敗點吧.必勝點和必敗點的概念 p點 必敗點,換而言之,就是誰處於此位置,則在雙方操作正確的情況下必敗。n點 必勝點,處於此情況下,雙方操作均正確的情況下必勝。必勝點和必敗點的性質 1 所有終結點是 必敗點 p 我們以此為基本前提進行推理,換句話說,...