Chieh's Blog

Because Of Coding

HDU 5269 ZYB loves Xor I

Chieh posted @ 2015年6月14日 11:10 in BestCoder , 537 阅读

飞机票:http://acm.hdu.edu.cn/showproblem.php?pid=5269

题意:给你一个数组A,A[i]^A[j]之后,假设为P,求lowbit(P)(就是P最低位为1的位置,然后就是2^为1位置)。然后求和,这里的话要计算两遍,即i和j j和i算两个,并不算一个。

分析:起先以为是最低位:不用为2的幂掌握的不够深刻啊。然后百度才知道要幂的。。。这次印象深刻了这种题的话,可以用分治,即分成两个块然后求值。具体怎么求值:

(1)先把所有的数转换为2进制。

(2)从最低位开始,如果是1就放入左边块,如果是0就放入右边块。(这里我是定义vector l,r ,每次是1就存入l,右边就存入r),这样的话就知道l里的元素和r里的元素是异或之后最低位为当前深度的2的幂,然后把l的大小*r的大小*2加到答案里去。*2是因为l和r算一边,然后r和l算遍。

(3)然后把l和r分别进行第二步。因为l和r已经不相干了。这里要及时退出,就是当l和r其中是0时就要退出,不然会TLE

总体复杂的O(n*logn),然后啪啪啪,就可以AC了

/*
Author:Chieh
Because Of Coding
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#define LL long long
#define INF 1e9
#define EPS 1e-9
using namespace std;
const int maxn=5*12345;
int T;
int n;
int  ai[maxn];
int bi[30];
struct he
{
    bool isok[30];
} Sky[maxn];
int MOD=998244353;
void getBir()
{
    for(int i=1; i<=n; i++)
    {
        memset(Sky[i].isok,0,sizeof(Sky[i].isok));
        for(int j=29; j>=0; j--)
        {
            if(ai[i]-bi[j]>=0)
            {
                ai[i]-=bi[j];
                Sky[i].isok[j]=1;
            }
        }
    }
}
void init()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)scanf("%d",&ai[i]);
    getBir();

}
LL ans;
void DFS(vector<int> V,int depth)
{
    if(depth==30)
    {
        return;
    }
    if(V.size()==0)return;
    vector<int> l;
    vector<int> r;
    for(int i=0; i<V.size(); i++)
    {
        int id=V[i];
        if(Sky[id].isok[depth])
        {
            l.push_back(id);
        }
        else
        {
            r.push_back(id);
        }
    }
    int ls=l.size();
    int rs=r.size();
    LL p=ls*rs;
    ans=(ans+((p*(bi[depth]%MOD)%MOD)*2)%MOD)%MOD;
    DFS(l,depth+1);
    DFS(r,depth+1);
}
int Case;
void play()
{
    ans=0;
    vector<int> V;
    for(int i=1;i<=n;i++)V.push_back(i);
    DFS(V,0);
    printf("Case #%d: %I64d\n",++Case,ans);
}
int main()
{
    bi[0]=1;
    for(int i=1; i<=29; i++){bi[i]=bi[i-1]*2;}
    scanf("%d",&T);
    Case=0;
    while(T--)
    {
        init();
        play();
    }
    // cout << "Hello world!" << endl;
    return 0;
}

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter