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 }