P3917 异或序列

P3917 异或序列
暴力前缀异或枚举每一个区间,再求和,60分。
正解:
按每一位来做
对于区间[l,r],如果它对答案有贡献,区间中1的个数一定是奇数,可以按每一位取(1<<i)的前缀和,q[r]-q[l-1]一定是奇数,那只要保证端点值奇偶性不同即可。根据乘法原理,奇数*偶数就是满足条件的区间个数,这个是前缀和。
也可以用前缀异或,道理一样。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<cstring>
 8 #define inf 2147483647
 9 #define For(i,a,b) for(register long long i=a;i<=b;i++)
10 #define p(a) putchar(a)
11 #define g() getchar()
12 //by war
13 //2017.10.23
14 using namespace std;
15 long long n;
16 long long a[100010];
17 long long cnt;
18 long long ans;
19 void in(long long &x)
20 {
21     long long y=1;
22     char c=g();x=0;
23     while(c<'0'||c>'9')
24     {
25     if(c=='-')
26     y=-1;
27     c=g();
28     }
29     while(c<='9'&&c>='0')x=x*10+c-'0',c=g();
30     x*=y;
31 }
32 void o(long long x)
33 {
34     if(x<0)
35     {
36         p('-');
37         x=-x;
38     }
39     if(x>9)o(x/10);
40     p(x%10+'0');
41 }
42 int main()
43 {
44     in(n);
45     For(i,1,n)
46     {
47         in(a[i]);
48         a[i]^=a[i-1];
49     }
50     For(i,0,17)
51     {
52     cnt=0;
53     For(j,1,n)
54     if((a[j]>>i)&1==1)
55     cnt++;
56     ans+=cnt*(n-cnt+1)*(1<<i);    
57     }
58     o(ans);
59      return 0;
60 }

 

posted @ 2017-10-23 15:40  WeiAR  阅读(313)  评论(0编辑  收藏  举报