SG函數與組合博弈問題

把組合博弈問題抽象成一個有向無環圖,有n個棋子在上面移動,當AB兩方其中一方移動不了時另一方獲勝.
定義mex運算爲集合內沒有出現過的最小的自然數,則SG(x)=mex{SG(y)(其中y爲x所擴展出的狀態)}
結論:當有K組的博弈時若SG(n1)^SG(n2)^..SG(nK)!=0時先手獲勝,否則後手獲勝.
CF上的一道題:

A. The game of Osho
time limit per test2 seconds
memory limit per test64 megabytes
inputpowers.in
outputstandard output
Faheem and Faheema love to play what they call the game of Osho, in this game they choose a number N randomly, the first player subtracts a non-zero number Bk1 less than or equal to N from N, then the second player subtracts number Bk2 (where B is given and ki is a non negative integer number), then again the first and so on until one of the players loses when he/she can’t make any move. In other words, when it’s a player’s turn and N equals 0. For example let’s see this game when B=2 and N=3. The first player Faheem can subtract 1 or 2 the optimal move here is 1, N now equals 2. In her turn Faheema subtract 2 because 1 will make Faheem win, Faheem now can’t play any move and he loses.

After a while they found that this game is boring so they decided to upgrade it, their version combines multiple subgames of the form (Bi, Ni) and the player can choose which of them he wants to play his move in, a player loses when he/she can’t make a move.

Given the subgames, your job is to determine which player wins the whole game assuming that both players play optimally.

Input
The first line contains T, the number of test cases. The next T lines contain G (1 ≤ G ≤ 100) the number of subgames and then follows G pairs of integers (1 ≤ Bi, Ni ≤ 1, 000, 000, 000) describing each subgame.

Output
For each test case print 1 if the first player wins the game, or 2 if the second wins.

Examples
input
3
1 2 3
1 7 3
2 6 11 3 2
output
2
1
2
我是先打表找規律..

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;

#define ll long long
#define me(x) memset(x,0,sizeof(x))

ll f[105];
ll sg[500];
ll hashs[500];
ll fast(int a,int b)
{
  if (!b) return 1;
  if (b&1) return a*fast(a,b-1);
  ll t=fast(a,b/2); return t*t;
}
void  getsg(int b)
{

  int pos;
  for (int i=0;i<100;i++)
  {
    ll t=fast(b,i);
    if (t>1000000000) {pos=i-1;break;}
    f[i]=t;
    pos=i;
  }
  sg[0]=0;
  for (int i=1;i<=105;i++)
  {
    memset(hashs,0,sizeof(hashs));
    for (int j=0;f[j]<=i&&j<pos;j++)
    {
        hashs[sg[i-f[j]]]=1;
    }
    for (int j=0;;j++)
    {
      if (!hashs[j]) {sg[i]=j; break;}
    }
  }

}
int main()
{
  freopen("powers.in","r",stdin);
  int T;
  scanf("%d",&T);
  while (T--){
    //memset(sg,0,sizeof(sg));
    int n;
    scanf("%d",&n);
    int sum=0;
    for (int i=1;i<=n;i++)
    {
      int b,N;
      scanf("%d%d",&b,&N);
      //getsg(b);
      if (b&1) {if (N&1)sum=sum^1;else sum=sum^0;}
      else {
        if (N%(b+1)==b)sum=sum^2;
        else if (N%(b+1)&1) sum=sum^1;
             else sum=sum^0;
        }
    }
    if (!sum) printf("2\n");
    else printf("1\n");
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章