一个Nim的游戏变种题
Nim游戏的一个种类是:有n堆石子,每个人可以拿其中一堆石子的任意数量,不能不拿,而且每一步都是最优考虑,则有一下结论;
- 如果所有石子的异或和为0,则后手必赢
- 如果所有石子的异或和不为0,则先手必赢
那么知道这这个结论之后,本题就是多加了一步(小A可以先拿k个//注意,是必须拿k个或者不拿)穷举判断每一堆石子减去k个之后,是否还为0;
但是纯暴力穷举有可能超时,时间复杂度是O(N2),所以我就用了psum1[](前缀异或和),psum2[](后缀异或和),来记录(因为异或运算符合交换律);
#include <bits/stdc++.h>
using namespace std;
int main(void)
{
#define int long long
int n,k;
cin>>n>>k;
vector<int> v(n);
for (auto &i:v)cin>>i;
int ans = v[0];
for (int i = 1 ; i<n ; i++)ans ^= v[i];
sort(v.begin(),v.end());//没啥用的排序
if(ans != 0){
cout<<"YES"<<endl;
return 0;
}//计算异或和,如果符合第一条结论直接输出yes
vector<int> psum1(n,v[0]);
vector<int> psum2(n,v[n-1]);
for(int i = 1 ; i<n ; i++)psum1[i] ^= psum1[i-1];//前缀和
for(int i = n-2 ; i>=0 ; i--)psum2[i] ^= psum2[i+1];//后缀和
for (int i = 1 ; i<n-1 ; i++){
if(v[i] < k)continue;//k要小于等于石子的数量才可以拿
int res;
res = psum1[i-1] ^ psum2[i+1] ^ (v[i] - k);//计算减去k之后的和
if(res != 0){
cout<<"YES"<<endl;
return 0;
}
}
cout<<"NO"<<endl;//其余情况小B赢
return 0;
}
//本蒟蒻是第一次写题解,求dalao放过

京公网安备 11010502036488号