zoukankan      html  css  js  c++  java
  • BZOJ3759: Hungergame 博弈论+线性基

    学了新的忘了旧的,还活着干什么

    题意:一些盒子,每步可选择打开盒子和取出已打开盒子的任意多石子,问先手是否必胜

    搬运po姐的题解:

    先手必胜的状态为:给出的数字集合存在一个异或和为零的非空子集,则先手必胜

    证明:

    首先我们有状态A:当前的所有打开的箱子中的石子数异或和为零,且所有关闭的箱子中的石子数的集合中不存在一个异或和为零的非空子集

    易证A状态时先手必败

    先手有两种操作:

    1.从一个打开的箱子中拿走一些石子 那么根据Nim的结论 后手可以同样拿走一些石子使状态恢复为A状态

    2.打开一些箱子 由于未打开的箱子中不存在一个异或和为零的非空子集 所以打开后所有打开的箱子中石子数异或和必不为零 于是后手可以拿走一些石子使状态恢复为A状态

    故此时先手必败

    那么如果初始不存在一个异或和为零的非空子集,那么初始状态满足状态A,先手必败

    如果初始存在一个异或和为零的非空子集,那么先手一定可以打开所有的异或和为零的子集,使剩余箱子不存在异或和为零的非空子集,将状态A留给后手,先手必胜

     然后就是判断是否有子集异或为0,线性基求一下。

    update:其实当n>32时可以直接判断先手胜,因为int范围考虑每一个二进制位一定会有异或为0的 

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 35
     4 int read(){
     5   int x=0,f=1;char ch=getchar();
     6   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7   while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     8   return x*f;
     9 }
    10 int n,a[N],b[N];
    11 bool gauss(){
    12   memset(b,0,sizeof(b));
    13   for(int i=1;i<=n;i++){
    14     for(int j=30;j>=0;j--)
    15       if(a[i]>>j&1){
    16         if(!b[j]){b[j]=a[i];break;}
    17         else a[i]^=b[j];
    18       }
    19     if(!a[i])return 1;
    20   }
    21   return 0;
    22 }
    23 int main(){
    24   int T=read();
    25   while(T--){
    26     n=read();
    27     for(int i=1;i<=n;i++)a[i]=read();
    28     puts(gauss()?"Yes":"No");
    29   }
    30   return 0;
    31 }
    View Code

    3759: Hungergame

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 182  Solved: 131
    [Submit][Status][Discuss]

    Description

    由于施惠国的统治极其残暴,每年从13个区中每个区中选出2名“贡品”参加饥饿游戏,而参加游戏的人必须在险恶的自然环境中杀死其余的人才能存活。游戏只会有一个人活下来 凯特尼斯•伊夫狄恩和同区的皮塔•麦拉克在历经千难万阻后活了下来,然而残忍的游戏只允许一人存活,正当两人准备同时吃下有毒的果实自杀的时候,统治者被打动了,他说:你们两个人跟我玩一个游戏,你赢了,我就让你们两个都活下来。女主角凯特尼斯•伊夫狄恩接受了挑战。
    这个游戏是这样的,有n(n<=20)个箱子,每个箱子里面有ai(ai<=1000000000)个石头(怎么放进去的我就不知道了),两个人轮流进行操作(女主角先手),每一次操作可以将任意个(大于0个)未打开的箱子打开(一开始所有的箱子都是关闭的),或者在已经打开的一个箱子里拿走任意个(大于0个)石头(不能超过这个箱子现有的石头数)。最后谁无法操作谁就输了。
    现在给出n,和这n个箱子里的石头数ai,女主角想知道她是否有绝对的把握取得胜利(很明显她的对手“统治者”是绝顶聪明的)。

    Input

    第一行有一个正整数T(表示有T组测试数据),对于每组测试数据有两行,第一行为一个正整数n,接下来有 n个数,第 i 个数表示ai.
     

    Output

     有T行:对于每一个测试数据,如果先手可以必胜则输出“Yes”,否则输出“No”(没有引号)。
     

    Sample Input

    5
    5
    18 11 16 19 15
    5
    18 12 17 10 18
    5
    17 7 1 10 1
    5
    19 5 16 19 8
    5
    18 18 7 4 9

    Sample Output

    No
    Yes
    Yes
    Yes
    Yes

    HINT

    100%的数据:n<=20,T<=10,ai不超过1,000,000,000;
  • 相关阅读:
    Elasticsearch:使用function_score及soft_score定制搜索结果的分数
    Elasticsearch:Elasticsearch中的refresh和flush操作指南
    Elasticsearch:top_hits aggregation
    Linux 容器的使用
    编译Linux内核
    GIT的使用
    Linux 小知识翻译
    Linux 小知识翻译
    Linux 小知识翻译
    Linux 小知识翻译
  • 原文地址:https://www.cnblogs.com/wjyi/p/5593269.html
Copyright © 2011-2022 走看看