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 
View Code

 

posted @ 2015-05-25 18:52  idy002  阅读(649)  评论(0编辑  收藏  举报