2017校招真题在线编程 异或

来源:互联网 发布:ubuntu谷歌拼音输入法 编辑:程序博客网 时间:2024/06/07 05:15

思路:

将每个数字造成字典树的一条链。每次查询时,如果当前位置上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 14 2*/


原创粉丝点击