zoukankan      html  css  js  c++  java
  • 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");
        }
    }
     
     
     
     
  • 相关阅读:
    利用Github Actions自动保持 GitHub 提交状态常绿
    windows下搭建轻量级php代码审计环境
    jquery实现点击弹出对话框
    redis学习记录(1)Redis简介
    StatefulSet
    Pod
    Spark 写Hive指定动态分区
    我常用的git操作
    在C#中如何使用GetOpenFileName函数多选文件
    image matching challenge
  • 原文地址:https://www.cnblogs.com/candy99/p/6551284.html
Copyright © 2011-2022 走看看