1. 程式人生 > >【BZOJ2940】條紋(博弈論)

【BZOJ2940】條紋(博弈論)

span char 一個 處理 || long long 簡單 sizeof .com

【BZOJ2940】條紋(博弈論)

題面

BZOJ
神TM權限題。

題解

我們把題目看成取石子的話,題目就變成了這樣:
有一堆\(m\)個石頭,每次可以取走\(c,z,n\)個,每次取完之後可以把當前這堆剩下的石頭分成任意數量的兩堆(可以為空),不能操作者輸,判定勝負。
那麽這就是一個比較簡單的\(Multi-SG\)了,直接預處理\(SG\)函數即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MAX 1010
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int c,z,n,m,SG[MAX];
bool vis[MAX];
int main()
{
    c=read(),z=read(),n=read();
    for(int i=1;i<=1000;++i)
    {
        memset(vis,0,sizeof(vis));
        if(i>=c)
            for(int j=0;j<=i-c;++j)
                vis[SG[j]^SG[i-c-j]]=true;
        if(i>=z)
            for(int j=0;j<=i-z;++j)
                vis[SG[j]^SG[i-z-j]]=true;
        if(i>=n)
            for(int j=0;j<=i-n;++j)
                vis[SG[j]^SG[i-n-j]]=true;
        for(int j=0;;++j)if(!vis[j]){SG[i]=j;break;}
    }
    m=read();while(m--)puts(SG[read()]?"1":"2");
    return 0;
}

【BZOJ2940】條紋(博弈論)