【题目链接】
不贴题面了,题意如下:
给出一段代码,将输入的数据通过这段代码运算之后得到博弈的初始数组(石头数量),你每一次可以取连续的几堆,使Alice(先手)在玩的时候,可以获胜,即取走一部分异或值不为0的石头,即可保证获胜
分析:
看了大佬的题解才知道这个题怎么做,使用全部数字的连续子序列减去异或值为零的连续子序列的数量即可
以下例进行说明,若通过代码运算之后得到的石头数量分别为 1 2 3 2 3 2 1,设num=0,使用num对他们进行连续异或运算,得到的结果如下:
可以看到,num的值出现了相等的情况,以及等于0的情况
我们可以发现,这些相等的num值中间部分的异或值,必然为0(如1和1对应的2^3^2^3=0),以及num值等于零的时候,也是前面一部分的连续异或值为零的。代码如下
#include<iostream>
#include<vector>
#include<set>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const long long maxn = 1e5+7;
long long a[maxn] ;
map<long long,long long>ans;
int main()
{
long long N,t,S,W;
cin >> t;
while(t--)
{
ans.clear();
scanf("%lld%lld%lld",&N,&S,&W);
long long g = S;
for (long long i=0; i<N; i++)
{
a[i] = g;
if( a[i] == 0 ) { a[i] = g = W; }
if( g%2 == 0 ) { g = (g/2); }
else { g = (g/2) ^ W; }
}
long long t = 0;
ans[0]=1;
for(long long i = 0; i < N; i ++)
{
t^=a[i];
ans[t]++;
//cout <<a[i] << " t:" << t << " " << ans[t] <<endl;
}
map<long long,long long>::iterator it;
long long Ans = 0;
for(it = ans.begin(); it != ans.end(); it++)
{
Ans += (it->second)*(it->second-1)/2;
//cout << it->first <<" " << it->second<<endl;
}
long long ANS = N*(N+1)/2;
ANS-=Ans;
cout << ANS<< endl;
}
return 0;
}