题意:

给你一个集合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的更多相关文章

  1. 2019牛客多校第一场 I Points Division(动态规划+线段树)

    2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...

  2. 2019牛客多校第一场E ABBA(DP)题解

    链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 ABBA 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语 ...

  3. 2019牛客多校第一场H XOR 线性基模板

    H XOR 题意 给出一组数,求所有满足异或和为0的子集的长度和 分析 n为1e5,所以枚举子集肯定是不可行的,这种时候我们通常要转化成求每一个数的贡献,对于一组数异或和为0.我们考虑使用线性基,对这 ...

  4. 2019牛客多校第一场A-Equivalent Prefixes

    Equivalent Prefixes 传送门 解题思路 先用单调栈求出两个序列中每一个数左边第一个小于自己的数的下标, 存入a[], b[].然后按照1~n的顺序循环,比较 a[i]和b[i]是否相 ...

  5. 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 ...

  6. 2019 牛客多校第一场 D Parity of Tuples

    题目链接:https://ac.nowcoder.com/acm/contest/881/D 看此博客之前请先参阅吕凯飞的论文<集合幂级数的性质与应用及其快速算法>,论文中很多符号会被本文 ...

  7. 2019牛客多校第一场 E-ABBA(dp)

    ABBA 题目传送门 解题思路 用dp[i][j]来表示前i+j个字符中,有i个A和j个B的合法情况个数.我们可以让前n个A作为AB的A,因为如果我们用后面的A作为AB的A,我们一定也可以让前面的A对 ...

  8. 2019 牛客多校第一场 B Integration

    题目链接:https://ac.nowcoder.com/acm/contest/881/B 题目大意 给定 n 个不同的正整数 ai,求$\frac{1}{\pi}\int_{0}^{\infty} ...

  9. 2019牛客多校第一场E ABBA 贪心 + DP

    题意:问有多少个有(n + m)个A和(n + m)个B的字符串可以凑出n个AB和m个BA. 思路:首先贪心的发现,如果从前往后扫,遇到了一个A,优先把它看成AB的A,B同理.这个贪心策略用邻项交换很 ...

随机推荐

  1. 【原创】C++11:左值和右值(深度分析)

    ——原创,引用请附带博客地址 2019-12-06 23:42:18 这篇文章分析的还是不行,先暂时放在这以后再更新. 本篇比较长,需要耐心阅读 以一个实际问题开始分析 class Sub{} Sub ...

  2. 最新 北森java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.北森等10家互联网公司的校招Offer,因为某些自身原因最终选择了北森.6.7月主要是做系统复习.项目复盘.LeetCode ...

  3. ADB 常用命令及详解

    1.pull文件 adb pull (文件路径) (想要pull的路径) MacBook-Pro:~ caris$ adb pull /sdcard/Android/data/com.xiwi.log ...

  4. LeetCode 1047. 删除字符串中的所有相邻重复项(Remove All Adjacent Duplicates In String)

    1047. 删除字符串中的所有相邻重复项 1047. Remove All Adjacent Duplicates In String 题目描述 LeetCode1047. Remove All Ad ...

  5. 使用JMeter进行Apache Kafka负载测试

    1.卡夫卡负载测试 在这个Apache Kafka教程中,我们将了解如何使用Apache JMeter,如何在Apache Kafka上执行Kafka负载测试.此外,这个Kafka负载测试教程教我们如 ...

  6. 协议——IIC

    I²C即Inter-Integrated Circuit(集成电路总线),它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代设计出来的一种简单.双向.二线制总线标准.多用于主机和从机在数 ...

  7. jedis参数不当引发的问题总结

    jedis参数不当引发dubbo服务线程池耗尽异常 现象:一个dubbo服务偶发性的出现个别机器甚至整个集群大量报线程池耗尽的问题.一开始对问题的处理比较粗暴,直接增加了10倍的线程数.但是问题依然偶 ...

  8. 单实例dg软件从10.2.0.4版本安装至10.2.0.5.12

    DG环境搭建需求,因此安装与主库相同的软件版本 1.主库软件版本10.2.0.5.12 2dg环境提供的是全新的10.2.0.4.0 3.安装步骤,安装10.2.0.5 静默安装 psu安装10.2. ...

  9. 编译基于obs-studio的阿里巴巴直播工具tblive的过程和常见问题解决

    tblive 简介 tblive开源项目对应的产品是千牛主播,是一个独立的PC端主播工具,基于开源软件OBS Studio来修改定制. 项目说明 tblive是一款优秀的基于obs-studio的直播 ...

  10. Imagetragick RCE(CVE-2016–3714)复现

    CVE-2016–3714: 闲着没事突然想起这个洞来,借用vulhub复现一下 poc有很多:https://github.com/ImageTragick/PoCs 我用的 push graphi ...