bzoj 4017 子序列和的异或以及异或的和
位运算很好的一个性质是可以单独每一位考虑。。。。。
题解请看:http://blog.csdn.net/skywalkert/article/details/45401245
对于异或的和,先枚举位,求所有异或和和中该位为1的有多少个,再乘以该位的大小(2的多少次方)。
即单独每一位考虑,每位带的权不一样。
对于和的异或,只需知道每一位中和的改位为1的奇偶性,就可以知道最终的异或值上该位是0还是1。
也是单独考虑每一位,看该位为0或1的条件。
1 /************************************************************** 2 Problem: 4017 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:9896 ms 7 Memory:3544 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 #define N 100010 14 #define Mod 998244353 15 using namespace std; 16 17 typedef long long dnt; 18 19 int n; 20 int aa[N]; 21 22 namespace Task1 { 23 dnt ans; 24 int cnt[2]; 25 dnt mpow( dnt a, int b ) { 26 dnt rt; 27 for( rt=1; b; b>>=1,a=a*a%Mod ) 28 if( b&1 ) rt=rt*a % Mod; 29 return rt; 30 } 31 void main() { 32 for( int b=0; b<=20; b++ ) { 33 cnt[0] = cnt[1] = 0; 34 for( int i=1; i<=n; i++ ) { 35 int bb = (aa[i]>>b)&1; 36 int c0 = cnt[0]; 37 int c1 = cnt[1]; 38 cnt[0^bb] = c0; 39 cnt[1^bb] = c1; 40 cnt[bb]++; 41 ans = (ans+cnt[1]*mpow(2,b)) % Mod; 42 } 43 } 44 printf( "%lld ", ans ); 45 } 46 }; 47 namespace Task2 { 48 dnt s[N]; 49 dnt disc[N], dtot; 50 int bit[2][N]; 51 dnt ans; 52 void init() { 53 memset( bit, 0, sizeof(bit) ); 54 } 55 void modify( int bit[], int a, int delta ) { // a in [1,n] 56 for( int i=a; i<=dtot; i+=i&-i ) 57 bit[i] += delta; 58 } 59 int query( int bit[], int a ) { 60 int rt = 0; 61 for( int i=a; i; i-=i&-i ) 62 rt += bit[i]; 63 return rt; 64 } 65 void main() { 66 for( int i=1; i<=n; i++ ) 67 s[i] = s[i-1] + aa[i]; 68 for( int b=0; b<=35; b++ ) { 69 dnt cnt = 0; 70 dnt mask = (1LL<<b) - 1; 71 dtot = 0; 72 disc[++dtot] = 0; 73 for( int i=1; i<=n; i++ ) 74 disc[++dtot] = s[i] & mask; 75 sort( disc+1, disc+1+dtot ); 76 dtot = unique( disc+1, disc+1+dtot ) - disc - 1; 77 init(); 78 modify( bit[0], lower_bound(disc+1,disc+1+dtot,0)-disc, +1 ); 79 for( int i=1; i<=n; i++ ) { 80 dnt bmid = (s[i]>>b) & 1; 81 dnt brgt = s[i] & mask; 82 int irgt = lower_bound( disc+1, disc+1+dtot, brgt ) - disc; 83 if( bmid ) { 84 cnt += query( bit[0], irgt ); 85 cnt += query( bit[1], dtot ) - query( bit[1], irgt ); 86 } else { 87 cnt += query( bit[0], dtot ) - query( bit[0], irgt ); 88 cnt += query( bit[1], irgt ); 89 } 90 modify( bit[bmid], irgt, +1 ); 91 } 92 ans |= (cnt&1) ? (1LL<<b) : 0; 93 } 94 printf( "%lld\n", ans ); 95 } 96 }; 97 98 int main() { 99 scanf( "%d", &n ); 100 for( int i=1; i<=n; i++ ) 101 scanf( "%d", aa+i ); 102 Task1::main(); 103 Task2::main(); 104 } 105