先简单的介绍一下^
0^0=0;
0^1=1;
1^0=1;
1^1=0;
1.一道非常经典的博弈论题目
链接 https://www.acwing.com/problem/content/893/
对于这题我们只需要
int res=0;
将res与每一堆的石子数量异或一下
最后判断res是不是0;
是0则必败,不是0则必胜;
#include <bits/stdc++.h>
using namespace std;
int a[100010];
int main()
{
int n,x;
int t; cin>>t;
while(t--)
{
cin>>n;
int res=0;
for(int i=1;i<=n;i++)
{
cin>>x;
res ^=x;
}
if(res==0) cout<<"Second"<<endl;
else cout<<"First"<<endl;
//system("pause");
}
system("pause");
return 0;
}
题目链接
https://ac.nowcoder.com/acm/contest/26125/A
这道题刚开始一点思路没有,后突然发现
他的每一次操作都是取奇数个石子;
这样的话就意味着
两个人经过一轮操作 取走了偶数个石子,如果原本是奇数个,那么最后一次操作一定是先手的,反之最后一次操作一定是后手的
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
//cin>>n>>m;
if((n+m)%2==1) cout<<"win"<<endl;
else cout<<"lose"<<endl;
}
// system("pause");
return 0;
}
题目链接
https://ac.nowcoder.com/acm/contest/26125/B
这道题我犯了两个错误,
第一:我把操作:将第X堆石堆的数量改为有,看成了减去y;
这导致了我测样列找错了很久,不可饶恕的错误;
第二:我没有注意到q是1e5的,写了个o(n^2)暴力,最后tle了;
这是t了的代码
在这里插入代码片#include <bits/stdc++.h>
using namespace std;
const int N=1000010;
int a[N];
int main()
{
int n,q;
int x,y,m=1;
cin>>n>>q;
int res;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=q;i++)
{
res=0;
cin>>x>>y;
a[x]=y;
for(int i=1;i<=n;i++)
{
res^=a[i];
}
if(res) cout<<"Kan"<<endl;
else cout<<"Li"<<endl;
// else
// {
// if(res) cout<<"Kan"<<endl;
// else cout<<"Li"<<endl;
// }
}
//system("pause");
return 0;
}
那么我们该如何改进呢,这里要用到一个小技巧
a异或x再异或x=a;
所以我们完全可以先预处理得到所有值的异或值
再对每一次的操作进行处理,这样只需要o(n),是不可能被卡时间的
#include <bits/stdc++.h>
#include <stdlib.h>
using namespace std;
const int N=1000010;
int a[N];
int main()
{
int n,q;
int x,y,m=1;
cin>>n>>q;
int res=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
res^=a[i];
}
for(int i=1;i<=q;i++)
{
cin>>x>>y;
res^=a[x];
res^=y;
a[x]=y;
if(res) cout<<"Kan"<<endl;
else cout<<"Li"<<endl;
}
system("pause");
return 0;
}