zoukankan      html  css  js  c++  java
  • [TJOI2017]异或和

    题目描述

    在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的。所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的 简单。但今天小明遇到了一个序列和的难题,这个题目不仅要求你快速的求出所有的连续和,还要快速的求出这些连续和的异或值。小明很快的就求出了所有的连续 和,但是小明要考考你,在不告诉连续和的情况下,让你快速求是序列所有连续和的异或值。

    输入输出格式

    输入格式:

    第一行输入一个n,表示这序列的数序列 第二行输入n个数字a1,a2...an代表这个序列

    0<=a1,a2,...an,0<=a1+a2...+an<=10^6

    输出格式:

    输出这个序列所有的连续和的异或值

    输入输出样例

    输入样例#1:
    3
    1 2 3
    输出样例#1:
    0

    说明

    【样例解释】

    序列1 2 3有6个连续和,它们分别是1 2 3 3 5 6,则1 xor 2 xor 3 xor 3 xor 5 xor 6 = 0

    【数据范围】

    对于20%的数据,1<=n<=100

    对于100%的数据,1<=n <= 10^5

    一般这种异或都是按位一位一位做的

    对于某第k位,如果为1,那么说明

    所有连续和异或的这第k位为1

    如果满足这第k位为1的(s[i]-s[j])有cnt个

    如果cnt为奇数,那么说明答案的第k位也等于1

    如何求出第k位为1的(i,j)对数?

    如果sum[i]第k位为1:

    为了使第k位为1,要么sum[j]第k位为0且sum[j]前k-1位小于sum[i]前k-1位的大小

    原因是如果红色条件不成立,进位后就变成了0

    还有就是sum[j]第k位为1且sum[j]前k-1位大于sum[i]前k-1位的大小

    同理,也是进位的问题

    那么红色部分要求满足大小关系的对数,用两个树状数组就行

    第k位为0同理

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 int c[1000001][2],s[100001],a[100001],ans;
     7 int pw[21],n;
     8 void add(int x,int y)
     9 {
    10   while (x<=1000000)
    11     {
    12       c[x][y]++;
    13       x+=(x&(-x));
    14     }
    15 }
    16 int query(int x,int y)
    17 {
    18   int sum=0;
    19   while (x)
    20     {
    21       sum+=c[x][y];
    22       x-=(x&(-x));
    23     }
    24   return sum;
    25 }
    26 int main()
    27 {int i,j,flag,cnt;
    28   cin>>n;
    29   for (i=1;i<=n;i++)
    30     {
    31       scanf("%d",&s[i]);
    32       s[i]+=s[i-1];
    33     }
    34   pw[0]=1;
    35   for (i=1;i<=20;i++)
    36     pw[i]=pw[i-1]*2;
    37   for (i=0;i<=20;i++)
    38     if (pw[i]<=s[n])
    39       {
    40     memset(c,0,sizeof(c));
    41     flag=0;
    42     add(1,0);
    43     for (j=1;j<=n;j++)
    44       {
    45         int tmp=s[j]&pw[i];
    46         if (tmp) cnt=query(a[j]+1,0)+query(1000001,1)-query(a[j]+1,1);
    47         else cnt=query(a[j]+1,1)+query(1000001,0)-query(a[j]+1,0);
    48         if (cnt%2==1) flag^=1;
    49         add(a[j]+1,(bool)tmp);
    50         if (tmp) a[j]|=pw[i]; 
    51       }
    52     if (flag) ans|=(pw[i]);
    53       }
    54   cout<<ans;
    55 }
  • 相关阅读:
    20175126《Java程序设计》第七周学习总结
    20175126《Java程序设计》第六周学习总结
    软工实践个人总结
    第06组 Beta版本演示
    第06组 Beta冲刺(4/5)
    第06组 Beta冲刺(5/5)
    第06组 Beta冲刺(3/5)
    第06组 Beta冲刺(2/5)
    第6组 Beta冲刺(1/5)
    第06组 Alpha事后诸葛亮
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7612349.html
Copyright © 2011-2022 走看看