• bzoj1188: [HNOI2007]*游戏


    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1188

    思路:这题比较特殊,每个豆子是一个独立的游戏,SG的下标是豆子所处的位置。

    知道了这一点就很好做了。

    首先对于一个位置的两个豆子,一个人走一步,另一个人也可以走这一步,所以就抵消了

    从SG函数的角度理解,这两个豆子的SG值相同,最后反正会被异或掉。

    所以豆子数等于a[i]%2

    对于输出方案,枚举i,j,k,表示第一步由i移向j和k。

    怎么判断是否合法?只要判断移动后是否为先手必败,就是移动后的局面SG值为零。

    移动后的SG值只要通过原来的SG^SG[i]^SG[j]^SG[k]得到。

    这一步也很好理解,i处豆子少了一个,j,k豆子多了一个,都只要异或一下就可以了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int maxn=27;
    using namespace std;
    int T,n,a[maxn],sg[maxn],tot,ans;bool bo[20010];
    
    int getsg(int x){
    	if (sg[x]!=-1) return sg[x];//printf("xxxxx%d
    ",x);
    	memset(bo,0,sizeof(bo));
    	for (int i=1;i<x;i++)
    		for (int j=1;j<=i;j++)
    			bo[getsg(i)^getsg(j)]=1;//,printf("%d %d
    ",i,j)
    	for (int i=0;;i++) if (!bo[i]) return sg[x]=i;
    }
    
    int main(){
    	memset(sg,-1,sizeof(sg));
    	sg[1]=0;for (int i=2;i<26;i++) sg[i]=getsg(i);
    	//for (int i=1;i<=20;i++) printf("%d
    ",sg[i]);
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d",&n),ans=tot=0;
    		for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    		for (int i=1;i<=n;i++) if (a[i]&1) ans^=sg[n-i+1];
    		for (int i=1;i<=n;i++)
    			for (int j=i+1;j<=n;j++)
    				for (int k=j;k<=n;k++)
    					if (!(ans^sg[n-i+1]^sg[n-j+1]^sg[n-k+1]))
    						if (++tot==1) printf("%d %d %d
    ",i-1,j-1,k-1);
    		if (!tot) puts("-1 -1 -1");
    		printf("%d
    ",tot);
    	}
    	return 0;
    }



  • 相关阅读:
    12
    11
    10
    9
    8
    6. iOS APP 设计规范大全
    4. iOS中常用演示方法以及利弊
    我要写一篇动态计算tableView-cell高度的随笔
    doclever 5.5.1 安装及升级【原创】
    SPARROW-JS 从0开始写 0依赖,原生JS框架
  • 原文地址:https://www.cnblogs.com/thythy/p/5493550.html
Copyright © 2020-2023  润新知