【BZOJ3576】江南乐(博弈论)

题面

BZOJ
洛谷

题解

无论一堆石头怎么拆分,都并不能改变它是一个 MultiSG M u l t i − S G 的事实。
既然每一组的 F F 都是固定的,那么我们预处理所有的可能的堆,而将石子拆分成若干堆,也只需要考虑SG函数的值就好了。
但是这样子求 SG S G 值的复杂度是 O(V2) O ( V 2 ) 的,其中 V V 是值域,也就是105
再分析一下,将 x x 个式子拆分成的最少的石子个数是[x/m],最多的情况是 [x/m+1] [ x / m + 1 ]
因为 [x/m] [ x / m ] 可以数论分块,而对于 SG S G 函数值的影响之和奇偶性相关,所以只需要考虑 [x/m],[x/m+1] [ x / m ] , [ x / m + 1 ] 出现次数的奇偶性一共 4 4 中情况考虑。
[x/m]个数的奇偶性只和 m m 相关,[x/m+1]个数的奇偶性只和 x%m x % m 相关,而 x%m=xm[x/m] x % m = x − m [ x / m ]
[x/m] [ x / m ] 在数论分块中是定值,不需要额外考虑,那么只需要考虑 m m <script type="math/tex" id="MathJax-Element-1933">m</script>的奇偶性就好啦。
然而预处理的话复杂度比较爆炸,毕竟我们不一定所有的值都会被用到,那么就写一个记忆化搜索。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 100100
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 SG[MAX],vis[MAX];
int getSG(int x)
{
    if(~SG[x])return SG[x];
    for(int i=2,k;i<=x;i=k+1)
    {
        k=x/(x/i);
        for(int j=i;j<=min(i+1,k);++j)
        {
            int s=0;
            if((x%j)&1)s^=getSG(x/j+1);
            if((j-x%j)&1)s^=getSG(x/j);
            vis[s]=x;
        }
    }
    for(int i=0;;++i)if(vis[i]!=x)return SG[x]=i;
}
int main()
{
    int T=read(),F=read();
    memset(SG,-1,sizeof(SG));
    for(int i=0;i<F;++i)SG[i]=0;
    while(T--)
    {
        int n=read(),s=0;
        while(n--)s^=getSG(read());
        printf("%d ",(bool)s);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值