2017校招真題線上程式設計 異或
阿新 • • 發佈:2019-02-19
思路:
將每個數字造成字典樹的一條鏈。每次查詢時,如果當前位置上m是0,那麼必定可以取a[i]的相反值。
如果m在這個位置上是1,那就必須取與a[i]在當前位置上的相反值
#include <stdio.h> #include <algorithm> #include <cstring> #include <bitset> using namespace std; const int N=33; struct node { node *nxt[2]; int val,num; node() { val=num=0; fill(nxt,nxt+2,nullptr); } }; node *root; int n,m; void update(int k) { bitset<N> bit=k; int kk; node *cur=root; root->val=0; for (int i=17; i>=0; --i) { kk=bit[i]; if( cur->nxt[kk]==NULL) { node *tmp=new node(); cur->nxt[kk]=tmp; } cur=cur->nxt[kk]; cur->num++; } } long long query(node *t,int k ) { long long ans=0; bitset<N> bitm=m; bitset<N> bitn=k; for(int i=17;i>=0&&t!=NULL;--i) { int nm=bitm[i]; int nn=bitn[i]; if(nm==0){ if(t->nxt[nn^1]!=NULL) ans+=t->nxt[nn^1]->num; t=t->nxt[nn]; } else t=t->nxt[nn^1]; } return ans; } int a[100005]; int main() { int T,val,s; root =new node(); scanf("%d%d",&n,&m); for (int i=0; i<n; ++i) { scanf("%d",&a[i]); update(a[i]); } long long ans=0; for (int i=0; i<n; ++i) { ans+=query(root,a[i] ); } printf("%lld\n",ans/2); return 0; } /* 2 1 4 2 */