zoukankan      html  css  js  c++  java
  • [POI2004]GRA

    Description
    让我们考虑一个在m x 1 的板子上玩的游戏,板子被从1 到 m编号. 现在板子上有n 个棋子, 每个都严格占据板子上的一个格子. 没有一个棋子占据格子m. 每个单独的移动遵循以下原则: 移动的人选择一个棋子把它移动到比它大的格子中第一个未被占领的格子里去. 两个选手交替移动, 谁先占据格子m, 谁赢.下面是一个例子(m = 7), 一个选手可以把2 移到 4, 把3 移到 4 或者把6 移动到 7.

    我们说当前选手的移动是winning当且仅当他移动以后令一选手无论如何都无法赢他.
    我们想知道先手有多少个移动是winning的.

    Input
    第一行有两个数m and n (2 <= m <= 109, 1 <= n <= 106, n < m) .
    然后接下来n个上升的整数表示初始被占据的格子编号.

    Output
    输出先手有多少移动是winning的.

    Sample Input
    For the following input data1:
    5 2
    1 3
    For the following input2 data:
    5 2
    2 3

    Sample Output
    the correct answer1 is:
    1
    the correct answer2 is:
    0


    本题看上去情况较多,有点复杂,但其实本题是Staircase Nim(阶梯Nim)的一个变种,我们只需要一些转换便可将其变成Staircase Nim。(Staircase Nim请参考浅谈算法——博弈论中的例8)

    本题显然只能将石子移到m-2上,谁先移到m-1谁输。我们考虑将其转化,连续的一段石子是其后面一个阶梯上的石子,两个连续的一堆间隔的空阶梯数是空格数。

    肯定要加优化,也就是略去一些空阶梯,否则(10^9)直接炸飞。细节巨多……

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x>=10)     print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e6;
    int val[N+10],step[N+10];
    int main(){
    	int m=read(),n=read(),tmp=0,tot=0,ans=0;
    	for (int i=1;i<=n;i++)	val[i]=read();
    	if (val[n]==m-1){
    		ans=1;
    		for (int i=n-1;i&&val[i+1]-val[i]==1;i--)	ans++;
    		printf("%d
    ",ans);
    		return 0;
    	}
    	val[n+1]=m-1;
    	for (int i=n;i;i--)
    		if (val[i+1]-val[i]==1)	step[tot]++;
    		else	if (val[i+1]-val[i]==2)	step[++tot]=1;
    		else	if ((val[i+1]-val[i]-1)&1)	tot+=3,step[tot]=1;
    		else	tot+=2,step[tot]=1;
    	for (int i=1;i<=tot;i+=2)	tmp^=step[i];
    	if (tmp){
    		for (int i=1;i<=tot;i+=2)	if ((step[i]^tmp)<step[i])	ans++;
    		for (int i=2;i<=tot;i+=2)	if ((step[i-1]^tmp)>step[i-1]&&(step[i-1]^tmp)<=step[i-1]+step[i])	ans++;
    		printf("%d
    ",ans);
    	}else	putchar('0');
    	return 0;
    }
    
  • 相关阅读:
    VUE ElementUI Tree JAVA Mybatis实现 麦克斯
    VUE 创建工程 项目 麦克斯
    Go——关于Time包
    etcd——是什么做什么如何用
    php——composer安装与使用
    TinyXml——Linux下TinyXml的编译
    Mac下eclipse安装 lombok 插件
    gitlab——搭建私有gitlab服务
    apachehttpd——Linux/Mac源码安装apachehttpd
    mongo——通过docker查看mongo集群的状态和数据
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/8433592.html
Copyright © 2011-2022 走看看