1. Bash Game

There is only a stack of n items from which two people take turns. It is stipulated to take at least one item at a time and at most m items at a time. The winner is the last one who takes light.

If n%(m+1)==0 the later hand will win, otherwise the first hand will win, if n>m, take n%(m+1) for the first time, if n<=m, any one between n~m for the first time

II. Wazov Game

There are two stacks of several items each. Two people take at least one item from one of them in turn, at most unlimited, or take the same item from both stacks at the same time, which stipulates that the final winner will win.

while(cin>>n1>>n2) { if(n1>n2) swap(n1,n2); temp=floor((n2-n1)*(1+sqrt(5.0))/2.0); if(temp==n1) cout<<"Backhand wins"<<endl; else cout<<"Win first"<<endl; }

3. Nim Game

There are any stacks of items, and the number of items in each stack is arbitrary. Both parties take turns to take items from each stack. Only part or all of the items can be taken from one stack at a time. At least one item can be taken. The person who takes the last item wins.

Conclusion: If the value obtained is 0, the first hand will lose, otherwise the first hand will win.

If the rule is transformed into a maximum of K in the Nim game, then only mod(k+1) is needed for each heap of stones.

while(cin>>n) { temp=0; for(int i=0;i<n;i++) { cin>>ans; temp^=ans; } if(temp==0) cout<<"Backhand wins"<<endl else cout<<"Win first"<<endl; }

4. Game of Fibonacci

There is a stack of items, two people take turns to take at least one by hand, no upper limit at most, but they can't get all the items out. After that, they can't take more than twice the number of items last taken and at least one item at a time. The person who takes the last item wins.

Conclusion: First-hand wins if and only if n is not a Fibonacci number (n is the total number of items)

const int N = 55; int f[N]; void Init() { f[0] = f[1] = 1; for(int i=2;i<N;i++) f[i] = f[i-1] + f[i-2]; } int main() { Init(); int n; while(cin>>n) { if(n == 0) break; bool flag = 0; for(int i=0;i<N;i++) { if(f[i] == n) { flag = 1; break; } } if(flag) puts("Second win"); else puts("First win"); } return 0; }

Fair Portfolio Game:

(1) Two participants.

(2) The set of state of a game situation is limited.

(3) For the same situation, the operational set of the two players is identical.

(4) Players take turns in the game.

(5) When the game is over when the operation cannot be performed, the one that cannot perform the operation at this time is counted as a loss.

(6) No matter how the game is played, it can always end in a limited number of steps.

SG function:

g(x)=mex{g(y)|y is the successor of x}

Mex: Operates on a set to represent the smallest non-negative integer that does not belong to the set, such as mex{0,1,2,3}=4,mex{2,3,5}=0

SG Theorem: g(G)=g(G1) g(G2) g(G3)...The SG value of a game is XOR of its sub-game SG value

Conclusion: When g(G)=0, the first hand must lose, otherwise, the first hand must win

Solving Model:

1. If the original game is divided into several independent sub-games, the SG function value of the original game is the exclusive or of the SG function values of all its sub-games.

That is sg(G)=sg(G1)sg(G2)...^sg(Gn).

2. Consider that there is no subgame and calculate its SG value.

The calculation method of SG value: (key)

1. Continuous integers with optional steps of 1~m can be directly modeled, SG(x) = x% (m+1);

2. The optional number of steps is arbitrary, SG(x) = x;

3. Optional steps are a series of discontinuous numbers, calculated using a template.

Template 1-Tabulate

const int N=10005; int f[N],SG[N],S[N]; //N must be large enough to contain all cases void getSG(int n,int m) //n for the length of the SG and m for the length of the f array { int i,j; sort(f,f+m); memset(SG,0,sizeof(SG)); //Because SG[0] always equals 0, i starts from 1 for(i = 1; i <= n; i++) { //Reset successor sets of the previous state each time memset(S,0,sizeof(S)); for(j = 0; f[j] <= i && j<m; j++) S[SG[i-f[j]]] = 1; //Mark the SG function value of the succeeding state for(j = 0;; j++) if(!S[j]) { //Query for the minimum non-zero value in the SG value of the current succeeding state SG[i] = j; break; } } }

Template 2-Search

const int N=10000; vector<int>e[N]; //Adjacency table int sg[N]; //sg is all initialized to -1 int getsg(int x) { if(sg[x]!=-1) return sg[x]; int mex[N]; memset(mex,0,sizeof(mex)); for(int i=0;i<e[x].size();i++) mex[getsg(e[x][i])]=1; for(int i=0;;i++) { if(!mex[i]) return sg[x]=i; //Memorized Search } }