【2019牛客多校第一场】XOR
题意:
给你一个集合A,里边有n个正整数,对于所有A的、满足集合内元素异或和为0的子集S,问你∑|S|
n<=1e5,元素<=1e18
首先可以转化问题,不求∑|S|,而是求每个元素属于子集数的和,也就是统计每个元素对答案的贡献
(题解中说根据期望的线性?我不懂期望和这个有啥关系,但是并不影响理解)
既然要求集合中的异或和,线性基就是针对这一类问题的一把好手
先给A求一个基R
对于没有被扔进R的元素,每一个元素对答案的贡献都是2^(n-|R|-1)
因为对于每个元素,先把它选走,剩下的不在R中的元素就可以随便选(也可以都不选),然后基R中一定能找出对应的元素组合把它们搞成0
为什么不用担心R中会有被选出元素相关的贡献没有统计?
注意线性基的性质:基中元素所有子集异或和都不同,保证了不会存在多种从R中选元素的方案,使得和不在R中选的元素异或和为0
接下来需要统计R基中元素对答案的贡献
遍历R中的元素,把它拎出来,给剩下的n-1个元素建个基D
如果被拎出来的元素还能插♂进基D,那就没救了,绝对异或不出0
否则它对答案的贡献就是2^(n-|D|-1),理由同上,不在D中的其他元素可以随便选,而从D中选子集的方案唯一
求基D可以加速,给n个元素中没在基R里的元素建个基B(这名字真鬼 = =)
然后每次把扔掉一个元素的基R和B合并
(线性基最好玩的地方就是用一个小集合代表一个大集合,还能保证不重复不遗漏)
这题我一开始把R中元素拎出来的方法是直接从基R的数组里挑,这种方法是错误的,反例:
7 8 6 8 9 8
如果直接从基里挑会直接把7和6(的第2,3个二进制位)一起挑出来,6本来还可以提供个0110的,但是往基里一放就被7搞没了
正确的姿势应该是开数组把进R基的元素存起来,然后在这个数组里挑出,剩下的重新进基
经验总结:
1.结构化程序设计很重要!之前开了3个数组,然后给每个数组都写个基,debug很难受
用把数组当函数参数的操作就可以只写一套线性基操作,需要用哪个基当参数扔进去即可
2.不要忘记对拍。包括看别人代码找自己错误的时候,有时候眼睛看不出来有啥问题,拍一拍就找到了
写个对拍也没多费事
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define LL long long
LL rd(){LL z=,mk=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mk;
}
int n; LL a[];
LL bssr[],bssb[],bssd[];
LL ans=,mo=;
bool flg[];
LL q[],hd=;
bool ist(LL x,LL y[]){
for(int i=;i>=;--i)if((LL)<<i&x){
if(!y[i]){
y[i]=x;
++y[];
return true;
}
x^=y[i];
}
return false;
}
bool chck(LL x,LL y[]){
for(int i=;i>=;--i)if((LL)<<i&x)
x^=y[i];
return !x;
}
LL qcp(LL x,int y){
LL z=;
for(;y;y>>=){
if(y&) z=(z*x)%mo;
x=(x*x)%mo;
}
return z;
}
void prvs(){
memset(bssr,,sizeof(bssr));
memset(bssb,,sizeof(bssb));
for(int i=;i<=n;++i) flg[i]=false;
ans=;
hd=;
return ;
}
int main(){
//freopen("ddd.in","r",stdin);
//freopen("ddd.out","w",stdout);
while(~scanf("%d",&n)){
prvs();
for(int i=;i<=n;++i) a[i]=rd();
for(int i=;i<=n;++i){
flg[i]=ist(a[i],bssr);
if(flg[i]) q[++hd]=a[i];
}
if(bssr[]==n){
printf("0\n");
continue;
}
ans+=(n-bssr[])*qcp(,n-bssr[]-)%mo;
for(int i=;i<=n;++i)if(!flg[i])
ist(a[i],bssb);
/*for(int k=0;k<=63;++k)if(bssr[k]){
memset(bssd,0,sizeof(bssd));
for(int i=0;i<=63;++i)
if(i!=k) bssd[i]=bssr[i];
bssd[64]=bssr[64]-1;
for(int i=0;i<=63;++i)if(bssb[i])
ist(bssb[i],bssd);
if(chck(bssr[k],bssd))
ans=(ans+qcp(2,n-bssd[64]-1))%mo;
}*/
for(int k=;k<=hd;++k){
memset(bssd,,sizeof(bssd));
for(int i=;i<=hd;++i)if(i!=k)
ist(q[i],bssd);
for(int i=;i<=;++i)if(bssb[i])
ist(bssb[i],bssd);
if(chck(q[k],bssd))
ans=(ans+qcp(,n-bssd[]-))%mo;
}
printf("%lld\n",ans);
}
return ;
}
【2019牛客多校第一场】XOR的更多相关文章
- 2019牛客多校第一场 I Points Division(动态规划+线段树)
2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...
- 2019牛客多校第一场E ABBA(DP)题解
链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 ABBA 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语 ...
- 2019牛客多校第一场H XOR 线性基模板
H XOR 题意 给出一组数,求所有满足异或和为0的子集的长度和 分析 n为1e5,所以枚举子集肯定是不可行的,这种时候我们通常要转化成求每一个数的贡献,对于一组数异或和为0.我们考虑使用线性基,对这 ...
- 2019牛客多校第一场A-Equivalent Prefixes
Equivalent Prefixes 传送门 解题思路 先用单调栈求出两个序列中每一个数左边第一个小于自己的数的下标, 存入a[], b[].然后按照1~n的顺序循环,比较 a[i]和b[i]是否相 ...
- 2019牛客多校第一场 A.Equivalent Prefixes
题目描述 Two arrays u and v each with m distinct elements are called equivalent if and only if RMQ(u,l,r ...
- 2019 牛客多校第一场 D Parity of Tuples
题目链接:https://ac.nowcoder.com/acm/contest/881/D 看此博客之前请先参阅吕凯飞的论文<集合幂级数的性质与应用及其快速算法>,论文中很多符号会被本文 ...
- 2019牛客多校第一场 E-ABBA(dp)
ABBA 题目传送门 解题思路 用dp[i][j]来表示前i+j个字符中,有i个A和j个B的合法情况个数.我们可以让前n个A作为AB的A,因为如果我们用后面的A作为AB的A,我们一定也可以让前面的A对 ...
- 2019 牛客多校第一场 B Integration
题目链接:https://ac.nowcoder.com/acm/contest/881/B 题目大意 给定 n 个不同的正整数 ai,求$\frac{1}{\pi}\int_{0}^{\infty} ...
- 2019牛客多校第一场E ABBA 贪心 + DP
题意:问有多少个有(n + m)个A和(n + m)个B的字符串可以凑出n个AB和m个BA. 思路:首先贪心的发现,如果从前往后扫,遇到了一个A,优先把它看成AB的A,B同理.这个贪心策略用邻项交换很 ...
随机推荐
- [LeetCode] 678. Valid Parenthesis String 验证括号字符串
Given a string containing only three types of characters: '(', ')' and '*', write a function to chec ...
- Kubernetes Pod应用的滚动更新(八)
一.环境准备 我们紧接上一节的环境,进行下面的操作,如果不清楚的,可以先查看上一篇博文. 滚动更新是一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新.滚动更新的最大的好处是零停 ...
- 转载:Python Web开发最难懂的WSGI协议,到底包含哪些内容?
原文:PSC推出的第二篇文章-<Python Web开发最难懂的WSGI协议,到底包含哪些内容?>-2017.9.27 我想大部分Python开发者最先接触到的方向是WEB方向(因为总是有 ...
- 使用win10自带虚拟光驱打开ISO镜像文件
使用win10自带虚拟光驱打开ISO镜像文件非常的简单. 工具/原料 电脑 win10系统 方法/步骤 第一种方法,双击ISO文件.打开“我的电脑”,打开所要打开的ISO文件所在的目录,双击要 ...
- SpringBoot系列教程JPA之query使用姿势详解之基础篇
前面的几篇文章分别介绍了CURD中的增删改,接下来进入最最常见的查询篇,看一下使用jpa进行db的记录查询时,可以怎么玩 本篇将介绍一些基础的查询使用姿势,主要包括根据字段查询,and/or/in/l ...
- 在ensp上STP配置和选路规则
原理概述 这次我们模拟的实验内容 搭建实验拓扑 搭建完拓扑之后,我们在交换机上启动STP服务,将交换机的STP模式改为普通生成树STP 配置完成之后我们来看一下S1生成树的状态(大约30秒之后,因为生 ...
- Clean code 关于注释、函数、命名的感想
最近在看代码整洁之道(Clean code)这本书,其实看的有点痛苦,因为越看就会越想自己写的代码是什么鬼?一些不知所云的命名,不整洁的代码格式,本想诠释代码的意思却添加了一段段废话,还有那些被强制加 ...
- QT 5.x 网络资源集锦
github上的好书:太好了: http://qmlbook.github.io/en/ch01/index.html 论坛: 基于QT的音乐创作软件:(是不是可以跟谷歌的深度学习艺术项目结合) ht ...
- kube-proxy运行机制分析【转载】
转自:http://blog.itpub.net/28624388/viewspace-2155433/ 1.Service在很多情况下只是一个概念,而真正将Service的作用实现的是kube-pr ...
- Selenium自动化获取WebSocket信息
性能日志 ChromeDriver支持性能日志记录,您可以从中获取域“时间轴”,“网络”和“页面”的事件,以及指定跟踪类别的跟踪数据. 启用性能日志 默认情况下不启用性能日志记录.因此,在创建新会话时 ...