HZAU 异或问题

来源:互联网 发布:mac 如何复制粘贴 编辑:程序博客网 时间:2024/05/05 18:52

1104: Sum and XOR

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 994  Solved: 56
[Submit][Status][Web Board]

Description

     Dr. Zeng is good at calculating sum of some numbers . Today , Yifan want to give a difficult work to Dr.Zeng .So,he told Dr.Zeng that he will get N numbers a1…an, and M options .When the option is 1 , Dr.Zeng should calculate the sum of the numbers . And the when the option is 2 , he will give Dr.Zeng a number D , then , change every ai into (ai xor d).

    Dr.Zeng is too lazy to calculate it ,so could you please help him ?

Input

    First line contains two integers N,M(0<N<5000000 , 0<M<100000)
    The second line contains N integer a1…an .
    Then the following M line . For each line , first a number op , if op == 2 ,there will be a number D.
    All the number is less then 2^25 .

Output

For each option 1 ,output a number ,the sum of a1…an.

Sample Input

2 31 212 51

Sample Output

311

HINT

Source

题意:告诉你n个数,现在做m个操作,包括以下两个操作:

1、求n个数的和

2、给一个数d,用d去异或n个数

一开始想用线段树来做。。真是智障啊。。。因为是对点的更新,线段树还是太费时了。

异或是对位进行操作的。。。所以遇到异或问题的时候一定要想想分解到位的时候是否能搞。。。

把n个数分解成二进制,然后统计每一位上有几个1(自己写的时候以为零的个数也要统计,后来发现是不用的,改变操作只关心1的个数),求总和的时候因为都知道每个位上有多少个1,所以总和很好算。

当给了d要求用其异或每个数的时候,也把d换成二进制,d的二进制表示上,仅当该位是1时,要将我们n个数统计出来的每一位1的个数和零的个数交换。

#include <iostream>#include <algorithm>#include <cmath>#include <cstring>#include <cstdio>using namespace std;const int maxn = 5000010;int maxLen;long long two[30];void init(){    int i;    long long ans = 1;    for(i=0;i<=30;i++){        two[i] = ans;        ans *= 2;    }}long long a[maxn];int in[30],one[30];void change(long long a,int index){    int p = -1;    if(index==-1){        while (a!=0) {            in[++p] = a%2;            a /= 2;        }        return;    }    while(a!=0){        ++p;        if(a%2){            one[p]++;        }        a /= 2;    }}int n,m;void myXOR(int len){    int i;    for(i=0;i<=len;i++){        if(in[i]==1){            one[i] = n-one[i];        }    }}long long getSum(){    long long ans = 0;    int i;    for(i=0;i<=maxLen;i++){        ans += one[i]*two[i];    }    return ans;}int main(){    //freopen("in.txt", "r", stdin);    //freopen("out.txt", "w", stdout);    int i,j;    init();    while (~scanf("%d%d",&n,&m)) {        long long now = 0;        long long sum = 0;        for(i=1;i<=n;i++){            scanf("%lld",&a[i]);            sum += a[i];            now = max(a[i],now);        }        for(i=0;i<=30;i++){            if(two[i]>=now){                maxLen = i;                break;            }        }        memset(one, 0, sizeof(one));        for(i=1;i<=n;i++){            change(a[i], i);        }        int op,nowLen;        long long z;        for(i=1;i<=m;i++){            scanf("%d",&op);            if(op==1){                printf("%lld\n",getSum());            }else{                scanf("%lld",&z);                memset(in, 0, sizeof(in));                change(z, -1);                for(j=0;j<=30;j++){                    if(two[j]>=z){                        nowLen = j;                        break;                    }                }                maxLen = max(maxLen,nowLen);                myXOR(nowLen);            }        }    }    return 0;}




先转载存着

0 0
原创粉丝点击