原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round8-H.html

题目传送门 - https://www.nowcoder.com/acm/contest/146/H

题意

  有 $n$ 堆石子,第 $i$ 堆有 $a_i$ 个。请你取出尽量多堆石子,使得取石子nim游戏后手必胜。输出你选择的石子堆数。

  $n,a_i\leq 5\times 10^5$

题解

  首先我们把题转化成:在 $n$ 个数中选择尽量多的数,使得他们的异或值为 $0$ 。

  然后我们把题转化成:在 $n$ 个数中选择尽量少的数,使得他们的异或值为一个特定值 $C$ 。其中 $C=a_1\ {\rm XOR} \cdots {\rm XOR}\ a_n$ 。显然,答案为 $n-$ 你选择的数的个数。

  考虑将 $a_i$ 二进制的每一维拆开,看作一个 $d$ 维向量。其中由于 $a_i\leq 2^{19}$,所以我们取 $d=19$ 。

  由于 $d$ 维线性无关向量组最多有 $n$ 个向量,所以我们最多在那些数字里面取 $d$ 个。

  我们考虑二分答案,假设选择小于等于 $k$ 个就可以组成 $C$ 了。

  我们如何验证:

  对于原数组每一个数出现的位置都记一下,然后把位置 $0$ 也搞一下,然后取它在异或卷积意义下的 $k$ 次幂,判断一下可不可以合成 $C$ 即可。这个用 FWT 做。

代码

#include <bits/stdc++.h>
using namespace std;
int read(){
int x=0;
char ch=getchar();
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
const int N=1<<19,mod=1e9+7,inv2=5e8+4;
int n,a[N],b[N],v=0;
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=1LL*x*x%mod)
if (y&1)
ans=1LL*ans*x%mod;
return ans;
}
void FWT(int a[],int n,int flag){
for (int d=1;d<n;d<<=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
int x=a[i+j],y=a[i+j+d];
a[i+j]=(x+y)%mod;
a[i+j+d]=(x-y)%mod;
if (flag==-1){
a[i+j]=1LL*a[i+j]*inv2%mod;
a[i+j+d]=1LL*a[i+j+d]*inv2%mod;
}
}
}
bool check(int x,int n){
for (int i=0;i<n;i++)
b[i]=Pow(a[i],x);
FWT(b,n,-1);
b[v]=(b[v]+mod)%mod;
return b[v]>0;
}
int main(){
n=read();
memset(a,0,sizeof a);
for (int i=1;i<=n;i++){
int x=read();
v^=x;
a[x]++;
}
a[0]++;
int m=1<<19;
FWT(a,m,1);
int L=0,R=19,mid,ans=19;
while (L<=R){
mid=(L+R)>>1;
if (check(mid,m))
R=mid-1,ans=mid;
else
L=mid+1;
}
printf("%d\n",n-ans);
return 0;
}

  

2018牛客网暑假ACM多校训练赛(第八场)H Playing games 博弈 FWT的更多相关文章

  1. 2018牛客网暑假ACM多校训练赛(第二场)E tree 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round2-E.html 题目传送门 - 2018牛客多校赛第二场 E ...

  2. 2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-I.html 题目传送门 - 2018牛客多校赛第三场 I ...

  3. 2018牛客网暑假ACM多校训练赛(第三场)G Coloring Tree 计数,bfs

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-G.html 题目传送门 - 2018牛客多校赛第三场 G ...

  4. 2018牛客网暑假ACM多校训练赛(第三场)D Encrypted String Matching 多项式 FFT

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-D.html 题目传送门 - 2018牛客多校赛第三场 D ...

  5. 2018牛客网暑假ACM多校训练赛(第十场)H Rikka with Ants 类欧几里德算法

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-H.html 题目传送门 - https://www.n ...

  6. 2018牛客网暑假ACM多校训练赛(第十场)F Rikka with Line Graph 最短路 Floyd

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-F.html 题目传送门 - https://www.n ...

  7. 2018牛客网暑假ACM多校训练赛(第十场)D Rikka with Prefix Sum 组合数学

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-D.html 题目传送门 - https://www.n ...

  8. 2018牛客网暑假ACM多校训练赛(第七场)I Tree Subset Diameter 动态规划 长链剖分 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round7-I.html 题目传送门 -  https://www.n ...

  9. 2018牛客网暑假ACM多校训练赛(第六场)I Team Rocket 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round6-I.html 题目传送门 - https://www.no ...

随机推荐

  1. Node.js的那些坑——如何让异步并发方法同步顺序执行(for循环+异步操作)

    1 前言 nodejs的回调,有时候真的是让人又爱又恨的,当需要用for循环把数据依次存入数据库,但是如果使用正常的for循环,永远都是最后一次值的记录,根本不符合要求. 解决此方案有几种,例如闭包( ...

  2. 使用第三方组件(django-redis)创建连接池

    settings里面: ##redis配置CACHES={ 'default':{ 'BACKEND':'django_redis.cache.RedisCache', 'LOCATION':'red ...

  3. 【Android开发经验】android:windowSoftInputMode属性具体解释

    本文章来自CSDN博客:http://blog.csdn.net/zhaokaiqiang1992.转载请注明地址! 在前面的一篇文章中,简单的介绍了一下怎样实现软键盘不自己主动弹出,使用的方法是设置 ...

  4. 幂的运算:X的n次幂

    计算X的n次幂,有多种算法 例子:计算2的62次方. method 1 :time = 1527 纳秒. 常规思路,进行61次的乘法! private static long mi(long X, l ...

  5. CSS弹性(flexible)盒子

    弹性盒子         弹性盒子由弹性容器(Flex container)和弹性子元素(Flex item)组成 弹性容器通过display:flex | inline-flex将其定义为弹性容器 ...

  6. ORA-00257 archiver error. 错误的处理方法

    archive log 日志已满 方法/步骤 1 SecureCRT登录服务器,切换用户oracle,连接oracle [root@userbeta~]# su - oracle [oracle@us ...

  7. NIO(三)

    使用直接缓冲区完成文件的复制(内存映射文件) package com.cppdy.nio; import java.nio.MappedByteBuffer; import java.nio.chan ...

  8. LeetCode(78):子集

    Medium! 题目描述: 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3] 输出: [ [3 ...

  9. 《剑指offer》 二维数组中的查找

    本题目是<剑指offer>中的题目 二维数组中的查找 题目: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个 ...

  10. 20165314 Linux安装及学习

    Linux的安装 安装虚拟机比我想象中要来的简单,虽然在这过程中出现了一些粗心大意导致的问题,但是重新再做一遍,问题就都解决了,比如: 未能加载虚拟光盘 在云班课的得到了同学的提示下我把虚拟机桌面的光 ...