題解: 現場想到了從結果的二進制的每一位考慮,每一位都是由比它低的低位決定的,但是規律沒找好。
舉個例子,結果的二進制的第3位(從0位開始)上是否爲1,是由0 到 2^4-1 之間的數決定,就是 0000 - 1111 之間所有數兩兩相加決定的,所以數組要先對2^4取餘。
而相加的結果,只有在1000 到 1111 ,也就是8~15之間,纔會讓第3位爲1,統計爲1的結果若是奇數,則最終結果的第三位上就是1,否則爲0
對 0 來說,和1000-1111 任意的數字相加,都會讓第3位爲1
對 0001 來說,和0111- 1110之間的任意數字相加,也滿足條件
0010 ~ 0110-1101
...
1111 ~ 0000-0000 和 1001~1111
總的來說,考慮第3位,對任意的x(x在0~2^4-1之間), 就是看看在[2^3-x ~ 24-x]和[24-1+23-x,24-1]兩個區間裏有多少個數字。求區間和,可以用樹狀數組。
考慮第k爲,對於任意的x(x在0~2^(k+1)-1 之間),統計[2k-x,2(k+1)-x] 和 [2(k+1)+2k -x-1,2^(k+1)-1] 這兩個區間的和.
因爲數組裏數字的範圍是107,任意兩個數字之和最大是2*107,所以我最多考慮到第24位,2^24。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <math.h>
using namespace std;
#define MAX (int)4e5+5
#define MAX2 (1<<25)
int a[MAX];
int c[MAX2+5];
int lowbit(int x)
{
return x&(-x);
}
void Add(int pos,int len,int x)
{
while(pos<=len)
{
c[pos]+=x;
pos+=lowbit(pos);
}
}
int sum(int pos)
{
if(pos<=0)
return 0;
int res=0;
while(pos>0)
{
res+=c[pos];
pos-=lowbit(pos);
}
return res;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
int ans=0;
int num=1;
for(int i=0;i<25;i++)
{
num<<=1;
memset(c,0,num*sizeof(int));
int res=0;
for(int j=0;j<n;j++)
{
int x = a[j]%num;
int xx = sum((num-1)-x+1);
int yy = sum((num>>1)-x);
res+= xx-yy;
if(x>num>>1) {
xx = sum(num);
yy = sum(num-(x-(num>>1)));
res+=xx-yy;
}
if(res&1)
{
res=1;
}
else
res=0;
Add(x+1,num,1);
}
if(res&1)
ans |= (1<<i);
}
printf("%d\n",ans);
return 0;
}