• [BZOJ3576][Hnoi2014]江南乐


    传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3576

    这个题一看就是SG函数那套理论的题……

    SG函数的转移也挺好推的

    考虑每个游戏单独的SG函数,各组游戏之间没有影响

    对于每个i,因为两堆石子间的差距最多为1 每个石子有$O(n)$种分割

    然后我们如果直接xjb暴力转移的话是$O(n^2)$的 只能拿到70分

    怎么办呢?

    发现 每一堆石子只会被分成[$frac{n}{i}$]和[$frac{n}{i}$]+1两种取值

    如果学过整除分块的同学就会发现 这不是整除分块裸题吗?

    整除分块一下,只有$sqrt n$种取值

    然后对两种数量的石子的堆数计算一下 根据异或的性质计算答案

    总时间效率$O(nsqrt n)$

    code:

    #include <bits/stdc++.h>
    using namespace std;
    int SG[100005],mex[100005],N;
    int T,f;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int Get_SG(int x){
        if (SG[x]!=-1) return SG[x];
        if (x<f) {
            SG[x]=0;
            return 0;
        }
        SG[x]=0;
        for (int j=2,r;j<=x;j=x/(x/j)+1){
            for (int i=j;i<=min(j+1,x);i++){
            int res=0,a=i-x%i,y=x%i,c;
            if (y&1) c=Get_SG(x/i+1),res^=c;
            if (a&1) c=Get_SG(x/i),res^=c;
            mex[res]=x;
            }
        }
        while (mex[SG[x]]==x)
            SG[x]++;
        return SG[x];
    }
    int main(){
        //freopen("game.in","r",stdin);
        //freopen("game.out","w",stdout);
        T=read(),f=read();
        memset(SG,-1,sizeof(SG));
        while (T--){
            N=read();
            int ans=0;
            for (int i=1;i<=N;i++){
                int a;
                a=read();
                ans^=Get_SG(a);
            }
        printf("%d ",ans?1:0);
        }
        return 0;
    }
  • 相关阅读:
    CentOS 6.5 伪分布式 安装 hadoop 2.6.0
    单例模式的思想简介
    最有二叉树 哈夫曼树
    二叉树2
    二叉树1
    栈与队列
    线性表
    字符串模式匹配KMP算法
    数据结构(四) 查找 排序
    数据结构(三) 图
  • 原文地址:https://www.cnblogs.com/si--nian/p/11181020.html
Copyright © 2020-2023  润新知