#1693 : 逆序异或和
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
描述
给定长度为N的序列A1, A2, ... AN,求
其中xor是按位异或运算。
输入
第一行包含一个整数N。
第二行包含N个整数A1, A2, ... AN。
对于60%的数据,1 ≤= N ≤ 5000
对于100%的数据,1 ≤ N ≤ 100000, 1 ≤ Ai ≤ 100000
输出
一个整数,表示答案。
3 2 3 1样例输出
5
题解:
一道神奇的数位dp。。
一位一位的处理。
统计这个数之前这一位有几个是0
然后根据当前位来处理。
用树状数组优化即可。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10,mod=1e9+7;
int n,m,k,t,d[20][maxn],p[maxn],a[maxn];
void add(int x,int y,int d[])
{
while(x)d[x]+=y,x-=x&(-x);
}
int get(int x,int d[])
{
int ret=0;
while(x<maxn)ret+=d[x],x+=x&(-x);
return ret;
}
int main()
{
int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
long long ret=0;
for(i=1;i<=n;i++)
{
int num=get(a[i]+1,p);
for(j=0;j<20;j++)
{
if(a[i]>>j&1)ret+=(1LL<<j)*(num-get(a[i]+1,d[j]));
else ret+=(1LL<<j)*get(a[i]+1,d[j]);
if(a[i]>>j&1)add(a[i],1,d[j]);
}
add(a[i],1,p);
}
printf("%lld\n",ret);
return 0;
}