• Xor and Sum(异或和+算术和)


    题目描述

    给定一个大小为N的数组A,第i个元素为Ai。

    问有多少的子区间[LR],满足区间数值异或和等于区间数值和,即:

         Al xor Al+1 xor…xor Ar = Al + Al+1 +…+Ar(l+1表示下标)
          a和b的xor即为a和b二进制表示按位取xor得到新数c的十进制表示
    5和12的xor计算如下:

    510=01012

    (12)10=(1100)2

    01012xor11002=(1001)2

    (1001)2=(9)10

    输入

    第一行给定一个整数N。
    第二行给定N个整数,第i个数即为Ai。
    1≤N≤2×10^5
    0≤A_i≤2^30

    输出

    输出满足条件的子区间LR的数量。

    样例输入

    10
    0 0 740 361 473 0 0 826 479 974


    样例输出

    18

    题解:

    xor运算可以视为二进制下没有进位的加法,加法运算本身是有进位的加法。

    那么可以简单得出这样一个性质:对于一个区间而言,如果异或和加法答案一样,那么把区间缩小答案肯定还是一样;如果异或和加法答案不一样,那么把区间扩大答案肯定还是不一样。

    于是我们就可以枚举区间右端点,去寻找最小的左端点,这个区间异或等于区间和,那么以这个区间右端点的合法区间个数就是区间的长度(左端点往里缩都是合法的)。

    这个可以预处理出前缀和还有前缀异或和,用双指针维护出来。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 #include<string.h>
     5 #include<string>
     6 #include<queue>
     7 #include<stdlib.h>
     8 #include<math.h>
     9 #define per(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep(i,a,b) for(int i=a;i>=b;--i)
    11 #define inf 0xf3f3f3f
    12 #define ll long long int 
    13 using namespace std;
    14 int p[200005];
    15 int s[200005];
    16 int z[200005];
    17 int main()
    18 {
    19     int m,a;
    20     cin>>m;
    21     z[0]=0;s[0]=0;
    22     per(i,1,m) 
    23     {
    24         cin>>a;
    25         s[i]=s[i-1]+a;
    26         z[i]=z[i-1]^a;
    27     }
    28     ll l=0,sum=0;
    29     per(i,1,m)
    30     {
    31         while((z[i]^z[l])!=(s[i]-s[l])) l++;
    32         sum+=i-l;
    33     }
    34     cout<<sum;
    35     return 0;
    36 }

    -

  • 相关阅读:
    大道至简第四章读后感
    进度条08
    大道至简第五章读后感
    加密算法
    程序从命令行接收多个数字,求和之后输出结果。
    用JAVA制作简单登录窗口
    进度条07
    冲刺07
    冲刺06
    冲刺05
  • 原文地址:https://www.cnblogs.com/jiamian/p/12446120.html
Copyright © 2020-2023  润新知