蓝桥杯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,一经查实,立即删除!

相关文章

ubuntu23 安装minio

要在Ubuntu 23版本上安装MinIO&#xff0c;您可以遵循以下步骤&#xff1a; 1. 下载MinIO Server二进制文件 访问MinIO官方下载页面&#xff08;https://min.io/download&#xff09;&#xff0c;或者直接在终端使用wget命令下载最新版本的MinIO二进制文件。假设您想要安装的…

【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…

Python课程设计(课设)源码哪里找?

在互联网上寻找免费的Python课程设计&#xff08;课设&#xff09;源码&#xff0c;可以参考以下几个途径&#xff1a; 开源平台&#xff1a;GitHub是一个非常受欢迎的开源代码托管平台&#xff0c;你可以在这里搜索相关的Python项目。很多开发者会将他们的项目开源&#xff0c…

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; 目…

Hot100-80(Leetcode763划分字母区间)

代码&#xff1a; class Solution {public List<Integer> partitionLabels(String s) {int n s.length();boolean f[] new boolean[n1];Map<Character,Integer> map new HashMap<>();for(int i0;i<n;i){if(!map.containsKey(s.charAt(i))){f[i]true;m…

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

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

一文了解低功耗蓝牙BLE

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

其他元素

img元素 在文档中显示图像&#xff0c;可以任意改变图像的大小和外观 属性值 src属性&#xff1a;指定图像的路径 alt属性&#xff1a;提供备用文本&#xff08;当网络延迟或src出错时显示&#xff09; <img src"../../picture/屏幕截图 2024-03-08 231030.png&quo…

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…

Python实战:打造简易四则运算计算器

Python实战&#xff1a;打造简易四则运算计算器 简介&#xff1a;本文将指导您编写一个简易的Python计算器程序&#xff0c;该程序支持基本的加减乘除运算。通过此教程&#xff0c;您将学习到Python编程语言的基础知识&#xff0c;并学会如何利用这些知识构建实用的应用程序。…

【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…

matlab 的PWM OUT代码在2023b与2024a中都报错

2023b运行程序内容&#xff1a; Monitor & Tune frequency and duty cycle of PWM signals on STMicroelectronics STM32F4xx Based Hardware Board Signal Monitoring and Parameter Tuning of Generated PWM Output - MATLAB & Simulink - MathWorks 中国报错内容&…

手搓ajax的封装

ajax的封装 前言 每一次发送请求我们都需要重复创建实例&#xff0c;配置请求 发送请求 获取数据&#xff0c;为了能够使用更加方便&#xff0c;我们对于ajax请求的步骤进行封装 同步的ajax请求 同步封装ajax请求可以通过返回值的方式返回后端的数据请求参数 type 请求方式ur…

Megatron-DeepSpeed-GPU-多机训练

Megatron-DeepSpeed-cuda-多机训练 1.从ngc拉取pytorch:24.03-py3镜像2.安装nvidia-docker、创建容器3.安装Megatron-DeepSpeed环境4.安装openmpi和ssh服务5.拷贝公钥6.安装pdsh7.升级protobuf8.准备数据集9.创建配置文件10.开始测试本文演示了Megatron-DeepSpeed-GPU-多机训练…

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…