【TJOI2017】异或和
题目描述
在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题目都是与序列的连续和相关的。所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的简单。但今天小明遇到了一个序列和的难题,这个题目不仅要求你快速的求出所有的连续和,还要快速的求出这些连续和的异或值。小明很快的就求出了所有的连续和,但是小明想考考你,在不告诉连续和的情况下,让你快速的求出序列所有的连续和的异或值。
输入格式
第一行输入一个\(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】异或和的更多相关文章
- 【BZOJ4888】[TJOI2017]异或和(树状数组)
[BZOJ4888][TJOI2017]异或和(树状数组) 题面 BZOJ 洛谷 题解 考虑每个位置上的答案,分类讨论这一位是否存在一,值域树状数组维护即可. #include<iostream ...
- 【bzoj4888】: [Tjoi2017]异或和 BIT-乱搞
[bzoj4888]: [Tjoi2017]异或和 题目大意:给定一个序列,求这个序列所有的连续和的异或值.(n<=1e5 ai<=1e6) 想了各种奇怪的方法就是不会做啊啊啊.. Orz ...
- 洛谷P3760 - [TJOI2017]异或和
Portal Description 给出一个\(n(n\leq10^5)\)的序列\(\{a_n\}(\Sigma a_i\leq10^6)\),求该数列所有连续和的异或和. Solution 线段 ...
- [TJOI2017]异或和
题目描述 在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的.所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的 简单.但今天小明遇到了一个序列和的难题,这个题目不 ...
- BZOJ.4888.[TJOI2017]异或和(树状数组)
BZOJ 洛谷 \(Description\) 求所有区间和的异或和. \(n\leq 10^5,\ \sum a_i\leq 10^6\). \(Solution\) 这样的题还是要先考虑按位做. ...
- Luogu3760 TJOI2017 异或和 树状数组
传送门 题意:给出一个长度为$N$的非负整数序列,求其中所有连续区间的区间和的异或值.$N \leq 10^5$,所有元素之和$\leq 10^6$ 设序列的前缀和为$s_i$,特殊地,$s_0=0$ ...
- P3760 [TJOI2017]异或和
题目描述 在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的.所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的简单.但今天小明遇到了一个序列和的难题,这个题目不仅 ...
- 【[TJOI2017]异或和】
这道题挺神仙的,毕竟这个异或是需要进位的 看到区间和我们很自然的就想到了前缀和 于是处理一下前缀和答案就变成了这个样子 \[⊕\sum_{i=1}^n\sum_{j=1}^{i}pre_i-pre_{ ...
- [BZOJ4888][TJOI2017]异或和(树状数组)
题目描述 在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的.所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的简单.但今天小明遇到了一个序列和的难题,这个题目不仅 ...
- BZOJ4888 [Tjoi2017]异或和 【树状数组】
题目链接 BZOJ4888 题解 要求所有连续异或和,转化为任意两个前缀和相减 要求最后的异或和,转化为求每一位\(1\)的出现次数 所以我们只需要对每一个\(i\)快速求出\(sum[i] - su ...
随机推荐
- FusionCharts simple demo for (html+js、APS.NET Webform、MVC)
做GIS或其他内部数据统计项目的应该对FusionCharts也不会太陌生,简单易用已无需多说什么了,只是有时候框架不同,实现起来也稍有差异 引用dll调用FusionCharts类的静态方法Rend ...
- java中抽象类跟接口的区别
额,好吧,本来是打算转载些神马的,但是搜资料的过程中发现了一个专注与java的人,那就关注啦,以后多进他blog学习学习:http://www.cnblogs.com/chenssy/p/337670 ...
- 微信小程序之wx.getLocation再次授权问题解决
首先,在page外定义一个公共函数用于发送获取位置的请求 var getLocation = function (that) { wx.getLocation({ type: 'wgs84', suc ...
- 执行CRUD总结
- ___pInvalidArgHandler already defined in LIBCMTD.lib(invarg.obj)
vs2013编译项目时出错,网上很多的解决方案全都是垃圾,根本不能用 不过也有不是垃圾的,就是下面这个: 关于采用静态链接编译生成EXE库函数重复定义问题 看了好多关于类似LIBCMT.lib(inv ...
- 解决"Windows 安装程序不允许从远程桌面连接安装"
msiexec /i c:\路径\安装程序 例如 msiexec /i c:\TortoiseSVN-1.7.2.22327-x64-svn-1.7.2.msi
- Java对象的强、软、弱和虚引用
本文介绍Java对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象 ...
- 虚拟机安装CentOS以及SecureCRT设置【完美无错版】
一.CentOS简介 CentOS是Linux的发行版之一,它安全.稳定.高效,是我最喜欢的Linux发行版之一.CentOS根据Red Hat Enterprise Linux开放源代码编译而成,与 ...
- mongo_1 新手之路
mongodb 进入.在bin目录下 至于安装各位自己查资料吧 .不废话了 直接上图.这种表示已经成功进入mongo 本人mongo 数据库存放地址.如有需要可以清空可以自己删除. 接下来就是 ...
- 图解KMP算法