zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    JS 创建对象的几种方式
    JS跨域笔记
    HTML5随笔
    css3随笔
    CSS3最简洁的轮播图
    canvas createRadialGradient 用法
    git 初级
    Oracle数据库字符集与国家字符集
    连接Oracle 19c出现ORA-28040:没有匹配的验证协议
    Vmware workstation虚拟机导入到esxi虚拟机
  • 原文地址:https://www.cnblogs.com/si--nian/p/11181020.html
Copyright © 2011-2022 走看看