zoukankan      html  css  js  c++  java
  • 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;
    }



  • 相关阅读:
    Hibernate对象状态
    Session接口常用方法
    Hibernate 映射文件基本概述
    Hibernate domain对象说明
    Hibernate配置文件说明
    Hiberante可配置参数
    Hibernate基本演示
    使用JSON数据格式模拟股票实时信息
    操作系统实验零——操作系统实验环境准备
    Shell脚本之for循环、while循环,if语句、case语句
  • 原文地址:https://www.cnblogs.com/thythy/p/5493550.html
Copyright © 2011-2022 走看看