• 【BZOJ4035】数组游戏(博弈论)


    【BZOJ4035】数组游戏(博弈论)

    题面

    BZOJ
    洛谷

    题解

    很明显是一个翻硬币游戏的变形,因此当前局面的(SG)函数值就是所有白格子单独存在的(SG)函数的异或和。
    那么,对于每一个位置考虑(SG)函数。
    (SG(x)=mex_{i=1}^{n/x}{oplus_{j=1}^i SG(jx) })
    这种东西很不好算,直接打个表,
    发现对于所有(n/x)相同的数,他们的(SG)函数都是相同的。
    那么数论分块一下就只有(O(sqrt n))个有效的的(SG)值了。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #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 SG1[MAX],SG2[MAX],n,Sqr,vis[MAX],tim;
    int getSG(int x){return x<=Sqr?SG1[x]:SG2[n/x];}
    int nt(int i){if(i==n)return n+1;return n/(n/(i+1));}
    void init()
    {
    	Sqr=sqrt(n);SG1[1]=1;
    	for(int i=2,nw;i<=n;i=nt(i))
    	{
    		++tim;nw=0;vis[nw]=tim;
    		for(int j=2,k;j<=i;j=k+1)
    		{
    			k=i/(i/j);
    			vis[nw]=vis[nw^getSG(i/j)]=tim;
    			if((k-j+1)&1)nw^=getSG(i/j);
    		}
    		for(int j=0;;++j)
    			if(vis[j]!=tim)
    			{
    				i<=Sqr?SG1[i]=j:SG2[n/i]=j;
    				break;
    			}
    	}
    }
    int main()
    {
    	n=read();init();
    	int T=read();
    	while(T--)
    	{
    		int m=read(),s=0;
    		while(m--)s^=getSG(n/read());
    		puts(s?"Yes":"No");
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    chart控件多个ChartArea
    winform chart画折线,波形图,多条数据
    C# Chart 折线图 多条数据展示
    task一个任务结束后执行另一个操作
    C#多线程同步 读写锁ReaderWriterLock的用法
    C# 多线程文件读写整理总结
    vue解决跨域问题
    接前端页面
    使用vue+zrender绘制体温单 三测单(2)
    使用vue+zrender绘制体温单 三测单(1)
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9503558.html
Copyright © 2020-2023  润新知