列表

详情


NC20456. [TJOI2017]异或和

描述

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

输入描述

第一行输入一个n,表示这序列的数序列 
第二行输入n个数字a1,a2…an代表这个序列 
0<=a1,a2,…an,0<=a1+a2…+an<=10^6 
1<=n <= 10^5 

输出描述

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

示例1

输入:

3
1 2 3

输出:

0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 116ms, 内存消耗: 8684K, 提交时间: 2019-12-20 19:28:59

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans; 
}
int n,s[100001],lim,ans;
struct szsz{
    int c[1000101];
	inline void add(int x,int y){for (++x;x<=lim+1;x+=-x&x) c[x]+=y;}
    inline signed answ(int x){rr int ans=0; for (++x;x;x-=-x&x) ans+=c[x]; return ans;}
    inline signed aasw(int l,int r){return answ(r)-answ(l);}
}c0,c1;
signed main(){
	n=iut();
	for (rr int i=1;i<=n;++i) s[i]=s[i-1]+iut();
	for (rr int k=0;(1<<k)<=s[n];++k){
		lim=(1<<k)-1; rr int sum=0;
		for (rr int i=0;i<=n;++i){
			rr int now=s[i]&lim;
			if ((s[i]>>k)&1) sum+=c0.aasw(-1,now)+c1.aasw(now,lim),c1.add(now,1);
			    else sum+=c1.aasw(-1,now)+c0.aasw(now,lim),c0.add(now,1);
		}
		ans+=(1<<k)*(sum&1),memset(c0.c,0,sizeof(c0.c)),memset(c1.c,0,sizeof(c1.c));
	}
	return !printf("%d",ans);
}

C++14(g++5.4) 解法, 执行用时: 71ms, 内存消耗: 8676K, 提交时间: 2020-06-30 12:45:13

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5,M=1e6+5;
 
inline int read(){
    int x=0; char ch=getchar();
    for(;!isdigit(ch);ch=getchar());
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
 
int n,a[N],f[2][M],ans,i,now,oe; 
 
inline void update(int T,int x){
	for(;x<=i;x+=x&-x) f[T][x]^=1;
}
 
inline int query(int T,int x){
	int an=0;
	for(;x;x-=x&-x) an^=f[T][x];
	return an;
}
 
int main(){
	n=read();
	for(i=1;i<=n;i++) a[i]=read()+a[i-1];
	
	for(i=1,now=0,oe;i<=a[n];now|=i,i<<=1){
		memset(f,0,sizeof(f)),oe=0;
		
		update(0,1);
		for(int j=1,u,p;j<=n;j++){
			u=(a[j]&i)?1:0,p=(a[j]&now)+1;
			oe^=query(u^1,p)^query(u,i)^query(u,p);
			update(u,p);
		}
		
		ans+=i*oe;
	}
	
	printf("%d\n",ans);
	return 0;
}

上一题