蓝桥杯23年第十四届省赛-异或和之和|拆位、贡献法

题目链接:

蓝桥杯2023年第十四届省赛真题-异或和之和 - C语言网 (dotcpp.com)

 1.异或和之和 - 蓝桥云课 (lanqiao.cn)

参考题解:

 蓝桥杯真题讲解:异或和之和 (拆位、贡献法)-CSDN博客

洛谷P9236 [蓝桥杯 2023 省 A] 异或和之和 题解_c加加区间异或问题洛谷ir-CSDN博客

说明:

1.需要知道一个重要的结论(图片来自参考题解):

注:为什么A^B=C可以得到B^C=A ?在原式上两边同时异或上一个B,根据异或的性质,B^B=0,与0异或等于本身。

2.那么由前缀和可以得出

(sum(j,i)为i和j这个区间上面的异或和,右下角第二排的式子等号两边同时异或上一个s[j-1]得到第一排的式子):

3.从推出的这个式子来看,sum[i,j]=s[i]^s[j-1],(i右端点,j左端点)

说明任意一个区间上面的异或和都可以转化成两个异或前缀和的异或和。再考虑到,对于一个二进制位来说,异或和结果为1的时候才会对结果有影响(贡献),而奇数个1异或为1,偶数个为0,对应到这里的两个数(前缀和)异或,那么就是一个前缀和为0,一个为1,那么把n个数都进行拆位,就可以 对每一个二进制位 做操作数是0或1(只有拆成二进制的0和1才能直接用前面的结论)的异或位运算。

于是统计,在第k位(从0开始数)上,n个数中对应前缀和为0、1的数量,记为n0,n1,那么最后在这一位上的对结果的贡献就是n0*n1*2^{k} 。

这里注意:需要把S[0]考虑进来,左端点位置为1的时候计算区间需要s[0] ,而S[0]为0 ,所以0的初始数量为1

为什么会是n0 * n1 * 2^{k} ?因为n0是前缀和为0的数量,n1是前缀和为1的数量,我们在n0个位置里面选一个,再在n1个位置里选一个,他们计算出来的区间异或和sum(i,j)是为1的,且这个sum(i,j)不重复,因为你计数的0和1的位置是不重复的,那么计算出来的sum(i,j)的至少由一个端点跟别的sum不一样,那么n0*n1是sum(i,j)为1的个数,乘上这一位上的基数即可。

4.另一种思路:

在参考题解第二个文章里,提出了另一种思路,既然

对于一个二进制位来说,异或和结果为1的时候才会对结果有影响(贡献),而奇数个1异或为1,偶数个为0 

那么我统计我当前位置是出现1的奇数次还是偶数次,根据

sum[i,j]=s[i]^s[j-1]

 为奇数次,s[i]为1,要求s[j-1]为偶数次;

为偶数次,s[i]为0,要求s[j-1]为奇数次(即要求总的次数为奇数)

 于是很容易去找(记前面为偶数次的 位置数 为 even,奇数次为odd):

s[i]为奇数次,是不是就有 even+1个 为奇数次1 的区间?(因为这even个偶数次的 位置都可以作为s[j-1]的这个j-1位置,还有s[0]=0,0也是偶数次,这个没被计数到,(1,i)也是一个奇数个的区间,所以还要加1)

s[i]为偶数次,是不是就有 odd个 为奇数次1 的区间,因为是要求s[j-1]为奇数次,所以不加1.

或者可以这样考虑:

s[i]为奇数次,even个前面为偶数次的 位置,这些位置第一次出现对应的数肯定是1,且这个1只出现一次(对应这个偶数),否则1的数量就变了,0可以出现无数次,那么就是对应一个偶数o,他出现的第一个位置m,a[m](假设a为第k位上,这n个数的01序列的数组名)为1,s[m-1]肯定只出现了o-1次,这个位置不能组成合法区间,去掉。

而对于一个奇数p,第一次出现的位置r,a[r]为1,s[r-1]为偶数次p-1,需要加上这个位置。

于是合法的区间=even-出现的偶数的数量(若出现2,4,则数量为2)+出现的奇数的数量

当s[i]为奇数次,奇数的数量比偶数数量多1,推出上面同样的式子。

s[i]为偶数次,二者相等,推出上面同样的式子。

5.注意:

数据范围,数组每个数小于等于2的20次方,那么要考虑的二进制位数就是21位,不是20位!!

代码:

仅异或前缀和

要枚举左右端点,时间复杂度n^{2} ,会超时。60%数据。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int ans=0;
int a[N];
int s[N];//异或前缀和 //vector<int> num[N];
signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];//ans+=a[i];s[i]=s[i-1]^a[i];}for(int i=1;i<=n;i++){for(int j=i;j<=n;j++){int sum=s[j]^s[i-1];// sum(i,j)^s[i-1]=s[j]两百年同时异或s[i-1]消掉左边的 s[i-1]ans+=sum;}}cout<<ans;return 0;
}

说明3对应代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int ans=0;
int a[N];
int s[N];
//异或前缀和 
int odd,even,cnt=0,radix=1;
signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i]; }radix=1;for(int i=0;i<=20;i++){//这里同样注意:需要把S[0]考虑进来,左端点位置为1的时候计算区间需要s[0] ,而S[0]为0 //所以0的初始数量为1 int n0=1,n1=0;for(int j=1;j<=n;j++){//求第i位上的二进制前缀和 s[j]=s[j-1]^(a[j]&1);if(s[j]==1){n1++;} else{n0++;}a[j]=a[j]>>1;}ans+=n0*n1*radix;radix=radix<<1;}cout<<ans;return 0;
}

说明4对应代码: 

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int ans=0;
int a[N];
int s[N];
//异或前缀和 
int odd,even,cnt=0,radix=1;
signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}// 对二进制的21个位置中的第j个位置算n个数的贡献 //注意:是 0-20位!!!有21个位置 for(int j=0;j<=20;j++){cnt=0;odd=0,even=0;//对第i个数而言,它的二进制形式的第j位(从0开始数),能找到的能贡献1的区间数,//这个区间是i和前i个数组成的。有多少个能贡献1的区间在第i位上结果就加上多少个1 (最后结果要乘上第j位对应的基数:2的j次方) for(int i=1;i<=n;i++){//对n个数计算第j位上的异或和之和 //注意:取出最后一位的方法 int tt=a[i]&1;//取出二进制位 if(tt==1){//计算二进制第j位上,到第i个数是出现了几个1,用前缀和累加可以在O(1)复杂度计算出 s[i]=s[i-1]+1;}else{s[i]=s[i-1];}if(s[i]%2==0){//到第i数出现了偶数个1,那么他能找到 前i项中为奇数次的数量 个贡献1的区间  even++;ans+=(odd)*radix;//注意乘上第j位对应的基数 }else{//到第i数出现了奇数个1,那么他能找到 前i项中为偶数次的数量+1 个贡献1的区间 odd++;ans+=(even+1)*radix;}a[i]=a[i]>>1;//第i个数左移一位,方便下一次取j+1位 }radix=radix<<1;//j+1位,基数变成原来的2倍    }//    for(int i=1;i<=n;i++){
//        for(int j=i;j<=n;j++){
//            int sum=s[j]^s[i-1];// sum(i,j)^s[i-1]=s[j]两百年同时异或s[i-1]消掉左边的 s[i-1]
//            ans+=sum;
//        }
//    }cout<<ans;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/792260.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【T5中的激活函数】GLU Variants Improve Transformer

【mT5中的激活函数】GLU Variants Improve Transformer 论文信息 阅读评价 Abstract Introduction Gated Linear Units (GLU) and Variants Experiments on Text-to-Text Transfer Transformer (T5) Conclusion 论文信息 名称内容论文标题GLU Variants Improve Transfo…

flutter获取手机中的系统路径信息

https://www.bilibili.com/video/BV1wE421g7sw获取系统中的路径 获取系统中的路径&#xff0c;并在这个路径中创建一个文本文件【str.txt】 然后进行写入【str.txt】 再读取这个文件【str.txt】 手机没有开通root权限无法看到写入到【应用程序文档目录】路径中的文件 用来…

MySQL故障排查与优化

一、MySQL故障排查 1.1 故障现象与解决方法 1.1.1 故障1 1.1.2 故障2 1.1.3 故障3 1.1.4 故障4 1.1.5 故障5 1.1.6 故障6 1.1.7 故障7​ 1.1.8 故障8 1.1.9 MySQL 主从故障排查 二、MySQL优化 2.1 硬件方面 2.2 查询优化 一、MySQL故障排查 1.1 故障现象与解决方…

【考研经验贴】24考研860软件工程佛系上岸经验分享【丰富简历、初复试攻略、导师志愿、资料汇总】

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文讲解24考研860软件工程佛系上岸经验分享【丰富简历、初复试攻略、导师志愿、资料汇总】&#xff0c;期待与你一同探索、学习、进步&#xff0c;一起卷起来叭&#xff01; 目…

玩转C语言——文件操作、预处理、编译、链接

前言&#xff1a; 经过前面的学习&#xff0c;我们已经对C语言的语法学习完毕了&#xff0c;今天&#xff0c;我们这节内容是为了修炼内功&#xff0c;为以后的学习打下一个坚实基础。话不多说&#xff0c;开始我们今天的学习吧&#xff01; 一、文件操作 1.⼆进制⽂件和⽂本⽂…

一文了解低功耗蓝牙BLE

低功耗蓝牙技术可以构建两种类型的设备:双模设备和单模设备。双模设备既支持经典蓝牙又支持低功耗蓝牙。单模设备只支持低功耗蓝牙。还有仅支持经典蓝牙的设备。 在链路层,设备被分为广播者、扫描者、从设备和主设备。广播者是传输数据包的设备,扫描者是接收广播者的数据包…

C语言 | Leetcode C语言题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; bool isMatch(char* s, char* p) {int m strlen(s);int n strlen(p);// dp[i][j] 表示 s 的前 i 个字符和 p 的前 j 个字符是否匹配bool dp[m 1][n 1];memset(dp, false, sizeof(dp));dp[0][0] true; // 空字符串和空模式匹配// 处理 …

00-JAVA基础-javassist字节码操作

字节码操作 什么是字节码 Java字节码&#xff08;Java bytecode&#xff09;是Java虚拟机&#xff08;JVM&#xff09;执行的一种虚拟指令格式。它是由Java编译器生成的&#xff0c;基于栈的指令集&#xff0c;用于在Java虚拟机上执行。字节码文件包含了JVM能够识别的指令&am…

【JSON2WEB】 12基于Amis-admin的动态导航菜单树

【JSON2WEB】01 WEB管理信息系统架构设计 【JSON2WEB】02 JSON2WEB初步UI设计 【JSON2WEB】03 go的模板包html/template的使用 【JSON2WEB】04 amis低代码前端框架介绍 【JSON2WEB】05 前端开发三件套 HTML CSS JavaScript 速成 【JSON2WEB】06 JSON2WEB前端框架搭建 【J…

Flume 拦截器概念及自定义拦截器的运用

文章目录 Flume 拦截器拦截器的作用拦截器运用1.创建项目2.实现拦截器接口3.编写事件处理逻辑4.拦截器构建5.打包与上传6.编写配置文件7.测试运行 Flume 拦截器 在 Flume 中&#xff0c;拦截器&#xff08;Interceptors&#xff09;是一种可以在事件传输过程中拦截、处理和修改…

FreeRtos入门-4 事件组与同步点

事件组 事件组 同步点 创建 xEventGroupCalc xEventGroupCreate();//1&#xff0c;创建事件组 xEventGroupSyc xEventGroupCreate() 设置 xEventGroupSetBits(xEventGroupCalc,(1<<0));//设置事件组bit0 位 xEventGroupSync(xEventGroupSyc,BUSYING,ALL,portMAX…

VB 通过COM接口解析PSD文件

最近有PS测评的需求&#xff0c;故而想到了解析psd文件&#xff0c;目的就是为了获取文档信息和图层信息&#xff1b;获取PS的图像信息有很多方式&#xff0c;有过程性的&#xff0c;比如监听PS的各种操作事件&#xff1b;有结果性的&#xff0c;比如本文写的解析PSD文件。 0.…

使用pip安装geopandas(24.4更新)

geopandas是我们用Python进行地理分析常用的库&#xff0c;在数据处理、分析、制图等场景中有着极为广泛的应用&#xff0c;但是在安装过程中会出现各种问题。​geopandas的安装方式有很多&#xff0c;今天我们选取较为简单的pip来进行geopandas的安装。 ​首先&#xff0c;我…

内部类(InnerClass)

概述 什么是内部类 将一个类A定义在另一个类B里面&#xff0c;里面的那个类A就称为内部类&#xff08;InnerClass&#xff09;&#xff0c;类B则称为外部类&#xff08;OuterClass&#xff09;。 为什么要声明内部类呢 具体来说&#xff0c;当一个事物A的内部&#xff0c;还有…

Java web第一次作业

1.学会用记事本编写jsp文件&#xff0c;并放进tomcat的相关目录下&#xff0c;运行。 源代码&#xff1a; <% page contentType"text/html;charsetUTF-8" language"java" %> <html> <head> <title>我的第一个JSP页面</ti…

JavaSE——运算符

1. 概念 运算符是一种用于执行特定操作的符号或关键字。在编程中&#xff0c;运算符用于对变量、常量和表达式进行操作&#xff0c;以产生一个结果。 作为一门计算机语言&#xff0c; Java 也提供了一套丰富的运算符来操纵变量。 Java 中运算符可分为以下&#xff1a;算术运算…

电商系列之促销

> 插&#xff1a;AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…

算法沉淀——动态规划篇(子数组系列问题(下))

算法沉淀——动态规划篇&#xff08;子数组系列问题&#xff08;下&#xff09;&#xff09; 前言一、等差数列划分二、最长湍流子数组三、单词拆分四、环绕字符串中唯一的子字符串 前言 几乎所有的动态规划问题大致可分为以下5个步骤&#xff0c;后续所有问题分析都将基于此 …

CSS之第一个CSS样式和CSS选择符

前端这些博客&#xff0c;我觉得都是固定的语法&#xff0c;故而不会以过多的文字进行描述&#xff0c;本系列博文均以实例和代码介绍的方式进行&#xff0c;主要按照代码进行。不会以过多的文字描述。 第一个CSS样式 <!DOCTYPE html> <html lang"en">…