HDU 5269 ZYB loves Xor I
Chieh
posted @ 2015年6月14日 11:10
in BestCoder
, 552 阅读
飞机票: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; }