题目描述

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

输入格式

第一行输入一个\(n\),表示这序列的数字个数。

第二行输入\(n\)个数字\(a_1,a_2,a_3\)...\(a_n\),代表这个序列。

\(0≤a_1,a_2,\)...\(,a_n,0≤a_1+a_2+\)...\(+a_n≤10^6\)。

输出格式,

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

数据范围

对于\(20\%\)的数据,\(1≤n≤1000\)

对于\(100\%\)的数据,\(1≤n≤10^5\)


直接暴力\(O(n^2)\),可以获得\(20\)分

考虑按位枚举,题目保证了\(0≤a_1+a_2+\)...\(+a_n≤10^6\)

那么显然,我们最多只需要枚举\(20\)位

对于枚举的每一位,我们希望快速地算出有多少和在这一位上有贡献\(1\)

显然,一个和我们可以通过前缀和的预处理,\(\sum_{i=l}^r=sum[r]-sum[l-1]\)

当我们知道了当前\(x\),\(sum[x]\)的第\(i\)位为\(1\)的时候,我们要知道以这一位为结束区间有多少贡献为\(1\)的

显然只有两种情况,当\(sum[y](y<x)\)的第\(i\)位也是\(1\)的时候,\(y\)的后面几位必须比\(x\)大才可以使得\(x\)的前面退位,使得区间\(\sum_{i=y-1}^x\)产生贡献

当\(sum[y](y<x)\)的第\(i\)位也是\(0\)的时候,\(y\)的后面几位必须比\(x\)小才可以保住\(x\)的贡献

而满足这样的两个条件,我们可以用树状数组来简单地维护一下

\(x\)的第\(i\)位为\(0\)的时候,一样的分析一下就好了

还有一个细节就是,计算贡献的时候,可能答案会超过int,那就让他自然溢出好了,就是最后计算的时候注意取模的正负即可


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#define LL long long using namespace std; inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
} inline void read(int &x){
char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
} inline void read(LL &x){
char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
} inline int read(char *s)
{
char c=nc();int len=0;
for(;!((c>='A' && c<='Z')||(c>='a' && c<='z'));c=nc()) if (c==EOF) return 0;
for(;((c>='A' && c<='Z')||(c>='a' && c<='z'));s[len++]=c,c=nc());
s[len++]='\0';
return len;
} inline void read(char &x){
for (x=nc();!(x=='?' || x=='+' || x=='-');x=nc());
} int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
} int n,a[100010],p2[100],c0[2000010],c1[2000010],ans[100];
const int M=20; void change0(int x,int y)
{
x++;
while (x<=p2[M]) c0[x]+=y,x+=x&(-x);
}
void change1(int x,int y)
{
x++;
while (x<=p2[M]) c1[x]+=y,x+=x&(-x);
}
int query0(int x)
{
x++;
int res=0;
while (x>0) res+=c0[x],x-=x&(-x);
return res;
}
int query1(int x)
{
x++;
int res=0;
while (x>0) res+=c1[x],x-=x&(-x);
return res;
} int main()
{
read(n);
for (int i=1;i<=n;i++)
read(a[i]);
p2[0]=1;
for (int i=1;i<=M;i++) p2[i]=2*p2[i-1];
memset(ans,0,sizeof(ans));
for (int i=1;i<=M;i++)
{
int s=0;
for (int j=1;j<=n;j++)
{
s+=a[j];
if ((s&p2[i-1])!=0) ans[i]++;
if ((s&p2[i-1])==0)
{
ans[i]+=query0(p2[i-1]-1)-query0(s%p2[i-1]);
ans[i]+=query1(s%p2[i-1]);
}
else
{
ans[i]+=query0(s%p2[i-1]);
ans[i]+=query1(p2[i-1]-1)-query1(s%p2[i-1]);
}
if ((s&p2[i-1])==0) change0(s%p2[i-1],1);else change1(s%p2[i-1],1);
}
s=0;
for (int j=1;j<=n;j++)
{
s+=a[j];
if ((s&p2[i-1])==0) change0(s%p2[i-1],-1);else change1(s%p2[i-1],-1);
}
}
int res=0,s=1;
for (int i=1;i<=M;i++)
res+=s*abs(ans[i]%2),s*=2;
print(res),puts("");
return 0;
}

【TJOI2017】异或和的更多相关文章

  1. 【BZOJ4888】[TJOI2017]异或和(树状数组)

    [BZOJ4888][TJOI2017]异或和(树状数组) 题面 BZOJ 洛谷 题解 考虑每个位置上的答案,分类讨论这一位是否存在一,值域树状数组维护即可. #include<iostream ...

  2. 【bzoj4888】: [Tjoi2017]异或和 BIT-乱搞

    [bzoj4888]: [Tjoi2017]异或和 题目大意:给定一个序列,求这个序列所有的连续和的异或值.(n<=1e5 ai<=1e6) 想了各种奇怪的方法就是不会做啊啊啊.. Orz ...

  3. 洛谷P3760 - [TJOI2017]异或和

    Portal Description 给出一个\(n(n\leq10^5)\)的序列\(\{a_n\}(\Sigma a_i\leq10^6)\),求该数列所有连续和的异或和. Solution 线段 ...

  4. [TJOI2017]异或和

    题目描述 在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的.所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的 简单.但今天小明遇到了一个序列和的难题,这个题目不 ...

  5. BZOJ.4888.[TJOI2017]异或和(树状数组)

    BZOJ 洛谷 \(Description\) 求所有区间和的异或和. \(n\leq 10^5,\ \sum a_i\leq 10^6\). \(Solution\) 这样的题还是要先考虑按位做. ...

  6. Luogu3760 TJOI2017 异或和 树状数组

    传送门 题意:给出一个长度为$N$的非负整数序列,求其中所有连续区间的区间和的异或值.$N \leq 10^5$,所有元素之和$\leq 10^6$ 设序列的前缀和为$s_i$,特殊地,$s_0=0$ ...

  7. P3760 [TJOI2017]异或和

    题目描述 在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的.所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的简单.但今天小明遇到了一个序列和的难题,这个题目不仅 ...

  8. 【[TJOI2017]异或和】

    这道题挺神仙的,毕竟这个异或是需要进位的 看到区间和我们很自然的就想到了前缀和 于是处理一下前缀和答案就变成了这个样子 \[⊕\sum_{i=1}^n\sum_{j=1}^{i}pre_i-pre_{ ...

  9. [BZOJ4888][TJOI2017]异或和(树状数组)

    题目描述 在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的.所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的简单.但今天小明遇到了一个序列和的难题,这个题目不仅 ...

  10. BZOJ4888 [Tjoi2017]异或和 【树状数组】

    题目链接 BZOJ4888 题解 要求所有连续异或和,转化为任意两个前缀和相减 要求最后的异或和,转化为求每一位\(1\)的出现次数 所以我们只需要对每一个\(i\)快速求出\(sum[i] - su ...

随机推荐

  1. verilog 之语法学习

    1.使用非基数表示的十进制视为有符号数.使用基数表示的十进制被视为无符号数. 2.线网中的值被解释为无符号数,整型寄存器中的值被解释为有符号的二进制补码数,. 3.如果选择表达式的值为 x.z,或越界 ...

  2. win7重新安装后删除文件权限不够(小技巧)

    选择文件,安全,编辑,如果用户权限可以编辑,那么赋予提示的用户权限. 如果此时用户不可编辑,那先把所属用户换了,安全,高级,所有者,更换所有者之后,权限就可以编辑了.

  3. 缓存 memcached 与 redis

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  4. Rest Framework 认证源码流程

    一.请求到来之后,都要先执行dispatch方法,dispatch方法方法根据请求方式的不同触发get/post/put/delete等方法 注意,APIView中的dispatch方法有很多的功能 ...

  5. HDFS的介绍

    设计思想 分而治之:将大文件.大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析: 在大数据系统中作用:为各类分布式运算框架(如:mapreduce,spark,te ...

  6. ASP.NET Core应用到Windows Service中

    托管到Windows Service中 众所周知,ASP.NET Core采用了和传统ASP.NET不同的托管和HTTP处理方式,即把服务器和托管环境完全解耦. ASP.NET Core内置了两个HT ...

  7. Elasticsearch之head插件安装之后的浏览详解

    前提, Elasticsearch之插件介绍及安装 https://i.cnblogs.com/posts?categoryid=950999&page=2  (强烈建议,从头开始看) 比如, ...

  8. 幂等性的含义和 HTTP请求方法的幂等性

    幂等性的含义和 HTTP请求方法的幂等性 1.什么是幂等性 =============== 幂等性,英文是idempotent,读作[aɪ'dɛmpətənt]. 它的含义如下: “Methods c ...

  9. 设置VMware Player中的虚拟机和宿主机共享文件

    设置VMware Player中的虚拟机和宿主机共享文件 试验环境: 虚拟机软件:VMware Player 6.0.3 宿主机os:windows7 虚拟机os:centos6.6(32位)   完 ...

  10. ThinkPHP5如何引用新建的配置文件?

    1.在Application文件夹下建立extra 文件夹,并把新建的配置文件(例如字典配置文件dictConfig.php等)放入此文件夹: 2.在代码中使用 Config::get("d ...