这道题是暂无评定
题目描述
让我们考虑一个在 m \times 1m×1 的板子上玩的游戏,板子被从 11 到 mm 编号。
现在板子上有 nn 个棋子,每个都严格占据板子上的一个格子,没有一个棋子占据格子 mm。
每个单独的移动遵循以下原则:移动的人选择一个棋子把它移动到比它大的格子中第一个未被占据的格子里去。两个选手交替移动,谁先占据格子 mm 谁赢。
我们在当且仅当他移动以后令一选手无论如何都无法赢他的时候说当前选手的移动称作 \text{winning}winning 操作。
我们想知道先手有多少个移动是 \text{winning}winning 操作。
输入格式
第一行有两个数 m,nm,n 。
然后接下来 nn 个上升的整数表示初始被占据的格子编号。
输出格式
输出先手有多少移动是 \text{winning}winning 操作。
输入输出样例
输入 #1 输出 #1
5 2 1
1 3
对于 100100 % 的数据:2 \le m \le 10^{9}, 1 \le n \le 10^{6}2≤m≤109,1≤n≤106 ,且有 n + 1 \le mn+1≤m 。
下面是一个例子:
在 m = 7m=7 的时候,一个选手可以把 22 移到 44,把 33 移到 44 或者把 66 移动到 77。
代码:
#include<cstdio>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define N 1000005
using namespace std;
int read(){
int x=0,f=1,ch=getchar();
for(;!isdigit(ch);ch=getchar()) f=(ch=='-')?-1:1;
for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
return x*f;}
void print(int x){
if(x<0) putchar('-'),x=~(x-1);
if(x>9) print(x/10);
putchar(x%10+48);}
int n,m,a[N],tot,b[N],SG,cnt;
void init(){
m=read(),n=read();
for(int i=1;i<=n;++i) a[i]=read();
if(a[n]==m-1){
for(int i=n;i>=1 && a[n]-a[i]==n-i;--i,++cnt);
print(cnt);
exit(0);
}
}
void CoreCode(){
for(int i=1;i<=n;++i){
a[i]=m-1-a[i]-(n-i+1);
if(!a[i]) break;
if(i==1 || a[tot]>a[i]) a[++tot]=a[i];
++b[tot];
}
for(int i=1;i<=tot;++i){
if(a[i]&1){
SG^=b[i];
}
}
for(int i=1;i<=tot;++i){
if(a[i]&1){
if((SG^b[i])<b[i]) ++cnt;
}
else{
int lst=i<tot && a[i+1]==a[i]-1?b[i+1]:0;
if((SG^lst)>lst && (SG^lst)<=lst+b[i]) ++cnt;
}
}
print(cnt);
}
int main(){
init();
CoreCode();
return 0;
}