bzoj 4017: Xiao Q's invincible XOR

4017: Xiao Q's invincible XOR

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 736  Solved: 242
[ Submit ][ Status ][ Discuss ]

Description

background
 
Little Q discovered the secret of XOR when he was learning bit operations.
 
describe
 
Xiao Q is a person who loves to learn. He often goes to Wikipedia (http://en.wikipedia.org/wiki/Main_Page) to study computer science.
 
Just now, Xiao Q has seriously studied a series of bitwise operators (http://en.wikipedia.org/wiki/Bitwise_operation), among which the bitwise XOR operator xor has a great influence on him. The bitwise XOR operator is a binary operator. Bitwise XOR is commutative, i.e. i xor j = j xor i.
 
He found that the bitwise XOR can be understood as if the corresponding bits of the binary bits of the numbers being operated are the same, the position of the result is 0, otherwise it is 1, such as 1(01) xor 2(10) = 3(11).
 
He also found that bitwise XOR can be understood as adding each bit of a number without carry, such as 3(11) xor 3(11) = 0(00).
 
So he thought of two problems about XOR based on a given sequence of non-negative integers A1, A2, ..., An, where n is the length of the sequence.
 
The first problem is that if we denote Ai xor Ai+1 xor ... xor Aj by f(i, j), then the sum of any f(i, j) for 1 <= i <= j <= n is How many.
 
The second problem is that if Ai + Ai+1 + ... + Aj is represented by g(i, j), then any xor of g(i, j) with 1 <= i <= j <= n in How much together.
 
For example, for the sequence {1, 2}, all f are {1, 2, 1 xor 2}, which adds up to 6; all g is {1, 2, 1 + 2}, which XOR adds up to 0.
 
He thinks these two questions are very interesting, so he found you, I hope you can solve these two problems quickly, the answer to the first question may be very large, you just need to output it to take 998244353 (a prime number) value of the modulo.
 

 

 

Input

The first line contains a positive integer n, which represents the length of the sequence.
 
The second line contains n non-negative integers A1, A2, ..., An, representing this sequence.
 

 

Output

Two integers representing the answers to two questions, separated by spaces, where the answer to the first question is modulo 998244353 (a prime number).
 

 

Sample Input

2
1 2

Sample Output

6 0

HINT

 

100% of the data satisfy n <= 10^5, Ai <= 10^6.

 

    Great question ahhhhhh.
    Obviously, the first question is the easy mode. It is a good contribution to directly process the prefix Xor array and directly dismantle it (because it is too simple, I will not talk about this part in detail hhhh).
     
    Second question,,, it's a little troublesome hhhhh
    Considering that the prefix sum may be at the 10^11 level, so our binary needs to consider the first 30 bits, and will involve a series of long long problems (which step may accidentally blow up the int hhhh, but in order to get a card Usually I try to use int...).
    Since the answer is all intervals and XOR'd together, so let's consider whether 2^i is 1 or 0 in the answer in turn, then go to: https://www.lydsy.com/JudgeOnline/problem.php? id=4888 , I used the routine I used to solve this problem in the early days (but it was too early to find hhhh in my blog), that is, when considering the ith digit, divide all the numbers into this digit is 1 And this bit is 0 two kinds of numbers, calculated separately (here I will leave you the link of pushing things hhhh), but the prefix sum of this question is too large, we need to discretize it.
    emmmm then it's done.
 
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int ha=998244353,maxn=100005;
int n,m,Xor[maxn],num[35][2],F[2][maxn],ky;
inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
inline void update(int T,int x){ for(;x<=ky;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;}
ll a[maxn],now,N[maxn],A[maxn],ci[66];

inline int solve1(){
	int ans=0;
	for(int i=0;i<=20;i++) num[i][0]++;
	for(int i=1;i<=n;i++){
		Xor[i]=a[i]^Xor[i-1];
		for(int j=0;j<=20;j++) ans=add(ans,ci[j]*(ll)((Xor[i]&ci[j])?num[j][0]:num[j][1])%ha);
		for(int j=0;j<=20;j++) num[j][(Xor[i]&ci[j])?1:0]++;
	}
	return ans;
}

inline ll solve2(){
	ll ans=0; int tmp=0;
	for(int i=1;i<=n;i++) a[i]+=a[i-1];
	
	for(int i=0;i<=40;now|=ci[i],i++,tmp=0){
		memset(F,0,sizeof(F));
		
		for(int j=1;j<=n;j++) A[j]=N[j]=a[j]&now;
		sort(N+1,N+n+1);
		ky=unique(N+1,N+n+1)-N-1;
		for(int j=1;j<=n;j++) A[j]=lower_bound(N+1,N+ky+1,A[j])-N;
		
		for(int j=1,u;j<=n;j++){
			u=(ci[i]&a[j])?1:0;
			tmp^=query(u^1,A[j])^query(u,ky)^query(u,A[j])^u;
			update(u,A[j]);
		}
		
		if(tmp&1) ans+=ci[i];
	}
	return ans;
}

int main(){
	ci [0] = 1; for (int i = 1; i <= 40; i ++) ci [i] = ci [i-1] + ci [i-1];
	scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",a+i);
	printf("%d ",solve1()),printf("%lld\n",solve2());
	return 0;
}

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325050687&siteId=291194637
XOR