BZOJ 3895: 取石子[SG函数 搜索]

Posted Candy?

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3895: 取石子[SG函数 搜索]相关的知识,希望对你有一定的参考价值。

有N堆石子
·从某堆石子中取走一个
·合并任意两堆石子
不能操作的人输。
100%的数据满足T<=100,  N<=50. ai<=1000
 

容易发现基础操作数$d=\sum a_i +n-1$
没有个数为1的堆还好说,有的话@#$%^&好麻烦啊啊啊啊啊怎么可能找规律
然后看题解,woc记忆化搜索
$f(i,j)$表示i个个数为1的堆,其他操作数为j的胜负态
枚举操作转移就行了,一定要枚举对!注意$j=1$时
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=51,M=50055;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
int n,f[N][M];
 
int dfs(int a,int b){
    int &now=f[a][b];
    if(now!=-1) return now;
    if(a==0) return now=b&1;
    if(b==1) return now=dfs(a+1,0);
     
    if(a && !dfs(a-1,b) ) return now=1;
    if(b && !dfs(a,b-1) ) return now=1;
    if(a && b && !dfs(a-1,b+1) ) return now=1;
    if(a>=2 && !dfs(a-2,b+2+(b!=0)) ) return now=1;
    return now=0;
}
int main(){
    //freopen("in","r",stdin);
    int T=read();
    memset(f,-1,sizeof(f));
    while(T--){
        n=read();
        int x=0,y=0,a;
        for(int i=1;i<=n;i++){
            a=read();
            if(a==1) x++;
            else y+=a+1;
        }
        if(y) y--;
        puts(dfs(x,y) ? "YES" : "NO");
    }
}

 

 
 
 
 

以上是关于BZOJ 3895: 取石子[SG函数 搜索]的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ3895]取石子

BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏 [Nim游戏 SG函数]

BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏(SG函数)

[bzoj4589]Hard Nim——SG函数+FWT

取石子(sg函数)

bzoj1022: [SHOI2008]小约翰的游戏John(博弈SG-nim游戏)