题意:

给你一个集合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. [LeetCode] 346. Moving Average from Data Stream 从数据流中移动平均值

    Given a stream of integers and a window size, calculate the moving average of all integers in the sl ...

  2. [LeetCode] 555. Split Concatenated Strings 分割串联字符串

    Given a list of strings, you could concatenate these strings together into a loop, where for each st ...

  3. Kubernetes StatefulSet

    StatefulSet 简介 在Kubernetes中,Pod的管理对象RC.Deployment.DaemonSet和Job都是面向无状态的服务.但现实中有很多服务是有状态的,特别是一些复杂的中间件 ...

  4. python面试题300道

    本文截取了一些面试题及解决方案: Python 基础 文件操作 模块与包 数据类型 企业面试题 Python 高级 设计模式 系统编程 Python 基础 什么是 Python?根据Python 创建 ...

  5. SpringAOP异常:org.springframework.aop.aspectj.AspectJExpressionPointcut cannot be cast to com.....

    Exception in thread "main" java.lang.ClassCastException: org.springframework.aop.aspectj.A ...

  6. MySQL必知必会3

    创建和操纵表 创建表 输入 CREATE TABLE customers ( cust_id int NOT NULL AUTO_INCREMENT, cust_name char(50) NOT N ...

  7. 【C++札记】类的继承

    继承 面向对象的设计思想,类对数据做了封装,并可以加入访问权限,类的继承是面向对象思想的精髓.类的继承可以让新类从以有的类中获得已有的特征.原有类称为基类或父类,新类称为派生类或子类. 语法: cla ...

  8. python技巧 — 整合 User-Agent 大全汇总

    一.IE 浏览器 而IE各个版本典型的userAgent如下:Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)Mozilla/4.0 (compat ...

  9. c# webapi 过滤器token、sign认证、访问日志

    1.token认证 服务端登录成功后分配token字符串.记录缓存服务器,可设置有效期 var token = Guid.NewGuid().ToString().Replace("-&qu ...

  10. ASP.Net Core 2.1+ Cookie 登录授权验证【简单Cookie验证】

    介绍 本文章发布于博客园:https://www.cnblogs.com/fallstar/p/11310749.html 作者:fallstar 本文章适用于:ASP.NET Core 2.1 + ...