BZOJ 3105:[cqoi2013]新Nim游戏

BZOJ 3105:[cqoi2013]新Nim游戏

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3105

题目大意:在传统的Nim取石子游戏中做了改变:两人刚开始可以取走任意堆石子(不包括全部)后进行传统游戏,问先手能否必胜,若必胜求出刚开始最少取多少石子。

线性基

传统Nim游戏先手必胜的前提条件为$a_0 \lxor a_1 \lxor a_2 \lxor ... \lxor a_{n-1} \neq 0$.

故若欲使新Nim游戏先手必胜,则需保证先手刚开始取完后剩下的元素线性无关.

而问最少取多少石子,只需将原数列降序排序,贪心构造极大线性无关组.

代码如下:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #define MAX_BASE 30
 4 using namespace std;
 5 typedef long long ll;
 6 ll n,a[105],b[105];
 7 bool cmp(ll a,ll b){
 8     return a>b;
 9 }
10 ll cal(){
11     ll ans=0;
12     for(int i=0;i<n;++i){
13         ll t=a[i];
14         bool f=0;
15         for(int j=MAX_BASE;j>=0;--j){
16             if(a[i]>>j&1){
17                 if(b[j])a[i]^=b[j];
18                 else{
19                     b[j]=a[i];
20                     f=1;
21                     for(int k=j-1;k>=0;--k)if(b[k]&&(b[j]>>k&1))b[j]^=b[k];
22                     for(int k=j+1;k<=MAX_BASE;++k)if(b[k]>>j&1)b[k]^=b[j];
23                     break;
24                 }
25             }
26         }
27         if(f)ans+=t;
28     }
29     return ans;
30 }
31 int main(void){
32     ll sum=0,ans;
33     scanf("%lld",&n);
34     for(int i=0;i<n;++i){
35         scanf("%lld",&a[i]);
36         sum+=a[i];
37     }
38     sort(a,a+n,cmp);
39     ans=cal();
40     for(int i=0;i<n;++i)
41         printf("%lld\n",b[i]);
42     printf("%lld\n",sum-ans);
43 }
时间: 2024-10-10 00:35:18

BZOJ 3105:[cqoi2013]新Nim游戏的相关文章

BZOJ 3105: [cqoi2013]新Nim游戏

3105: [cqoi2013]新Nim游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1064  Solved: 624[Submit][Status][Discuss] Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴.可以只拿一根,也可以拿走整堆火柴,但不能同时从超过一堆火柴中拿.拿走最后一根火柴的游戏者胜利. 本题的游

BZOJ 3105 [CQOI2013]新Nim游戏 ——线性基

[题目分析] 神奇的题目,两人都可以第一次取走足够多堆的石子. nim游戏的规则是,如果异或和为0,那么就先手必输,否则先手有必胜策略. 所以只需要剩下一群异或和为0就可以了. 先排序,线性基扫一遍即可(保留最多的不为0的堆) [代码] #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #include <map&g

bzoj 3105: [cqoi2013]新Nim游戏【线性基】

nim游戏的先手必胜条件是所有堆的火柴个数异或和为0,也就是找一个剩下火柴堆数没有异或和为0的子集的方案,且这个方案保证剩下的火柴个数总和最大 然后我就不会了,其实我到现在也不知道拟阵是个什么玩意-- 详见:https://blog.csdn.net/wyfcyx_forever/article/details/39477673 总之用线性基维护即可 #include<iostream> #include<cstdio> #include<algorithm> usin

BZOJ 3105: [cqoi2013]新Nim游戏 [高斯消元XOR 线性基]

以后我也要用传送门! 题意:一些数,选择一个权值最大的异或和不为0的集合 终于有点明白线性基是什么了...等会再整理 求一个权值最大的线性无关子集 线性无关子集满足拟阵的性质,贪心选择权值最大的,用高斯消元判断是否和已选择的线性相关 每一位记录pivot[i]为i用到的行 枚举要加入的数字的每一个二进制为1的位,如果有pivot[i]那么就异或一下(消元),否则pivot[i]=这个数并退出 如果最后异或成0了就说明线性相关... #include <iostream> #include &l

3105: [cqoi2013]新Nim游戏 异或高消 &amp;&amp; 拟阵

3105: [cqoi2013]新Nim游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 535  Solved: 317[Submit][Status][Discuss] Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴.可以只拿一根,也可以拿走整堆火柴,但不能同时从超过一堆火柴中拿.拿走最后一根火柴的游戏者胜利. 本题的游戏

【BZOJ】3105: [cqoi2013]新Nim游戏

http://www.lydsy.com/JudgeOnline/problem.php?id=3105 题意:k堆火柴,先手和后手在第一次拿的时候都能拿若干整堆火柴(但不能拿完),之后和nim游戏规则一样.问先手是否必胜且第一次最少拿多少能保证必胜.(k<=100) #include <bits/stdc++.h> using namespace std; typedef long long ll; ll ans; int s[105], a[105], n; bool cmp(con

BZOJ3105: [cqoi2013]新Nim游戏

题解: 线性基?类似于向量上的基底. 此题题解戳这里:http://blog.csdn.net/wyfcyx_forever/article/details/39477673 代码: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #incl

BZOJ3105: [cqoi2013]新Nim游戏 博弈论+线性基

一个原来写的题. 既然最后是nim游戏,且玩家是先手,则希望第二回合结束后是一个异或和不为0的局面,这样才能必胜. 所以思考一下我们要在第一回合留下线性基 然后就是求线性基,因为要取走的最少,所以排一下序,从大到小求. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<cmath> 6 #include<algor

【BZOJ3105】[cqoi2013]新Nim游戏 贪心+线性基

[BZOJ3105][cqoi2013]新Nim游戏 Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴.可以只拿一根,也可以拿走整堆火柴,但不能同时从超过一堆火柴中拿.拿走最后一根火柴的游戏者胜利. 本题的游戏稍微有些不同:在第一个回合中,第一个游戏者可以直接拿走若干个整堆的火柴.可以一堆都不拿,但不可以全部拿走.第二回合也一样,第二个游戏者也有这样一次机会.从第三个回合(又轮到