P9236 [蓝桥杯 2023 省 A] 异或和之和

首先,异或有一个重要的性质:

\[a\oplus b \oplus b=a
\]

因为 \(b\) 的二进制位一定与自己一样,根据异或的定义,得出 \(b\oplus b=0\),进而推出这个式子。

有了这个式子,区间异或和就可以像前缀和一样处理了。

我们可以求出每一项的前缀异或和,记作 \(q_i\),根据上面那条性质,可以仿照前缀和的形式写出区间 \([l,r]\) 的异或和(记作 \(S_{l,r}\))的 \(O(1)\) 求法式子:(下标均从 \(1\) 开始)

\[S_{l,r}=p_r\oplus p_{l-1}
\]

所以,我们用这个式子来求解每个区间的异或和,可以把每个子段的异或和的和转变为下面式子:(这里 \(p_0\) 默认取 \(0\) 值,因为还需要查询类似 \([1,i]\) 这种区间的值)

\[\sum_{i=1}^{n}\sum_{j=0}^{i-1}p_i\oplus p_j
\]

但这个做法的复杂度是 \(O(n^2)\),不够通过本题的数据范围,所以我们还需要在这个基础上继续优化。

在这个式子中,我们可以观察到,对于每一对 \(i,j\) 不相等的有序数对 \((i,j)\),\(p_i,p_j\) 都恰好只互相异或了一次。所以,问题又转化为了 \(n\) 个数,其中两两异或的求和。

这个时候会发现推式子已经到达尽头了,再怎么推也不会得到新的结论。必须从其他方面考虑问题,比如异或运算的计算原理的方面。可以考虑把每个数按二进制拆分,在每一位上统计该位的贡献。由于最后是两两异或的求和,所以二进制拆分后打乱不会影响结果。

由于异或的运算法则是如果同位数字不同,那么运算结果的这一位为 \(1\)。我们知道,只有二进制位为 \(1\) 对最终的结果(加和)有贡献,所以我们可以统计二进制结果为 \(1\) 的情况。

对于每一个 \(p_i\),我们将其按位拆分,并将结果存入计数数组 \(w_{i,j}\) 中。其中 \(i\) 表示第 \(i\) 个二进制位,\(j\) 表示这一位上为 \(j\)(只能为 \(0\) 或 \(1\)),\(w_{i,j}\) 表示在所有数中,第 \(i\) 个二进制位上为 \(j\) 的有 \(w_{i,j}\) 个。

由于这些数中必定两两异或,所以可以直接用乘法原理,求出该位最终为 \(1\) 的个数,最后乘上该位的权值就可以了。所以最后的答案为:(公式中 \(i\) 的范围上界到 \(20\) 是因为题目中说 \(A_i\le2^{20}\),最多只有 \(21\) 个二进制位)

\[\sum_{i=0}^{20}w_{i,0}\times w_{i,1}\times 2^i
\]

时间复杂度 \(O(n)\),可以通过本题。

#include <bits/stdc++.h>
using namespace std;
long long n,a[100010],q[100010],w[100010][2],ans=0;
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)q[i]=q[i-1]^a[i];
for(int i=0;i<=n;i++)
for(int j=20;j>=0;j--)
w[j][(q[i]>>j)&1]++;
for(int i=0;i<=20;i++)
ans+=w[i][0]*w[i][1]*(1<<i);
printf("%lld",ans);
return 0;
}

AC记录

Luogu P9236 [蓝桥杯 2023 省 A] 异或和之和 题解的更多相关文章

  1. 2018年第九届蓝桥杯B组第四题:摔手机题解

    摔手机 摔手机 动态规划  在蓝桥杯的时候遇到一次 当时没有做对  看了题解也没明白  如今再次遇到这个类似的题目 于是拿出来补补吧 摔手机题目如下: 星球的居民脾气不太好,但好在他们生气的时候唯一的 ...

  2. 第九届蓝桥杯省赛c/c++真题明码题解答案,另类excel解法思路

    直到快比赛才重视起之前学校给报了蓝桥杯,且这段时间一直在做Python,所以没做什么准备. 赛场上做这道题时连反码补码的知识点都记混,所以直接用了excel做这道题目,分享下做题思路.及题解. 标题: ...

  3. 第十届蓝桥杯省赛JavaB组个人题解

    前言 以下的第十届蓝桥杯Java B组省赛的题目题解只是我个人的题解,提供一些解题思路,仅作参考,如有错误,望大家指出,不甚感激,我会及时更改. 试题 A: 组队 ----- 答案:490 [问题描述 ...

  4. 日期求星期(java)-蓝桥杯

    日期求星期问题(java)-蓝桥杯 1:基姆拉尔森计算公式(计算星期) 公式: int week = (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7; 此处y,m,d指代年 ...

  5. 算法笔记_199:第二届蓝桥杯软件类决赛真题(C语言本科)

    前言:以下代码部分仅供参考,C语言解答部分全部来自网友,Java语言部分部分参考自网友,对于答案的正确性不能完全保证. 试题1 数论中有著名的四方定理:所有自然数至多只要用四个数的平方和就可以表示. ...

  6. 2018第九届蓝桥杯决赛(C++ B组)

    逛了大半个北京还是挺好玩de 第一题 标题:换零钞 x星球的钞票的面额只有:100元,5元,2元,1元,共4种. 小明去x星旅游,他手里只有2张100元的x星币,太不方便,恰好路过x星银行就去换零钱. ...

  7. 2016年蓝桥杯B组C/C++决赛题目

    2016年第七届蓝桥杯B组C/C++决赛题目 点击查看2016年第七届蓝桥杯B组C/C++决赛题解 1.一步之遥 从昏迷中醒来,小明发现自己被关在X星球的废矿车里. 矿车停在平直的废弃的轨道上. 他的 ...

  8. 2012年 蓝桥杯预赛 java 本科 题目

    2012年 蓝桥杯预赛 java 本科 考生须知: l  考试时间为4小时. l  参赛选手切勿修改机器自动生成的[考生文件夹]的名称或删除任何自动生成的文件或目录,否则会干扰考试系统正确采集您的解答 ...

  9. 蓝桥杯历届试题 地宫取宝 dp or 记忆化搜索

    问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能向右或向下行走. 走 ...

  10. 蓝桥杯---数独(模拟 || dfs)

    [编程题](满分33分) "数独"是当下炙手可热的智力游戏.一般认为它的起源是"拉丁方块",是大数 学家欧拉于1783年发明的. 如图[1.jpg]所示:6x6 ...

随机推荐

  1. 🎀Mybatis-Plus中的MetaObjectHandler

    简介 MetaObjectHandler 是一个非常有用的组件,用于处理实体对象中的字段填充逻辑,比如自动填充创建时间.更新时间.创建人.修改人等字段. 组件介绍 MetaObjectHandler ...

  2. CentOS linux安装jdk

    1.查找系统是否安装jdk java -versionrpm -qa | grep jdk 2.卸载原jdk rpm -e --nodeps jdk..(这里为自己jdk路径) 3.下载指定版本rpm ...

  3. Java 21 新特性

    Java 21 是 Java 语言的一次重要更新,引入了若干新的特性,提升了开发者的编程效率和代码质量.本文将详细介绍 Java 21 的新特性,包括基础概念.使用方法.常见实践以及最佳实践. 简介 ...

  4. php uninx时间戳转datetime对象,获取n秒前的dateime问题

    当时在网上搜了下这个问题,大多方法都是定义一个函数,在里面处理,后来网官网文档看到可以这么用,记录下. php时间戳转datetime对象 var_dump(new \Datetime('@'.tim ...

  5. 关于 IFreeSql 注入,与 AspectCore 冲突的说明

    FreeSql 以 MIT 开源协议托管于 github:https://github.com/2881099/FreeSql IFreeSql 作为 ORM 顶级对象,没有设置 NameSpace( ...

  6. Python3循环结构(二) while循环

    Python3 while循环 当循环次数无界时通常会使用while循环. 1.使用while循环输出九九乘法表 i=1 while i < 10: j = 1 while j < i + ...

  7. SpringBoot静态资源访问--转载

    转载地址:https://www.jianshu.com/p/d40ee98b84b5

  8. 完整版QQ(腾讯)开放平台操作指南(包含:qq登录能力获取等等)

    之前我和大家提过,我要购买第三方的APP服务,就相当于有自己的APP了,现在APP对接上线之前需要做大量的准备工作,在此把步骤分享给大家,这样可以节省大家很多时间. 完整版QQ(腾讯)开放平台操作指南 ...

  9. 代码视角-神经网络-Python 实现(上)

    说明: 就是巩固一下认识而已, 也是找了篇网上大佬的文章, 看了下写得还行, 抄一抄, 权当编程练习了, 目的成为了, 从代码的角度去认识这些, 莫名其妙的, 让人生畏的, 但其实简单的, 生物学名词 ...

  10. C++11 shared_ptr(智能指针)

    在确保new动态分配的内存空间在使用结束之后,释放是一件麻烦事.C++11模板库的头文件中定义的智能指针,即shared_ptr模板,就是用来解决这个问题的. 它是将new运算符返回的指针p交给一个s ...