异或之

问题 F: 异或之
时间限制: 1 Sec 内存限制: 256 MB
提交: 83 解决: 14
[提交][状态][讨论版]
题目描述
给定n个非负整数A[1], A[2], ……, A[n]。
对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数。求这些数(不包含A[i])中前k小的数。
注:xor对应于pascal中的“xor”,C++中的“^”。

输入
第一行2个正整数 n,k,如题所述。
以下n行,每行一个非负整数表示A[i]。

输出
共一行k个数,表示前k小的数。

样例输入
4 5
1
1
3
4
样例输出
0 2 2 5 5
似01Trie

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#define MAXN 770005
//#define LL long long
using namespace std;
int ds;
struct Trie
{
  int dfn;
  int cc;
  int ww;
  int z;
  int dep;
  Trie *ch[3]; 
  Trie() 
  {
     memset(ch,0,sizeof(ch));
     dfn=0;
     dep=0;
     cc=0;
     z=0;
  }
}node[MAXN*2],*root;
priority_queue<int,vector<int>,greater<int> >Q;
int n,t,sz,f[35][200005],bb[35],ff[35],g[250005];
inline Trie* newnode()
{
  sz++;
  return &node[sz];       
}
inline void insert(char *s,int kk)
{
  Trie *now=root; 
  int len=strlen(s);
  for(int i=0;i<len;i++)
  {
          now->z++;
        if(now->ch[s[i]-'0']==NULL)
        {
            now->ch[s[i]-'0']=newnode();
            now->ch[s[i]-'0']->dep=i+1;
            f[i+1][0]++;
            f[i+1][f[i+1][0]]=sz; 
        }
        now=now->ch[s[i]-'0'];
  } 
  now->z++;
  now->dfn=1;
  now->cc++;
  now->ww=kk;    
}
int jj,ee;
void dfs(Trie *now)
{
     if(now->ch[0])
     dfs(now->ch[0]);    
     if(now->ch[1])
     dfs(now->ch[1]);
     if(now->dfn)
     {
        jj=now->cc;
        //if(jj>=2)
       // return;
       for(int i=1;i<=jj;i++)
        g[++g[0]]=now->ww;;         
     }
}
inline void sfind()
{
      int hh,pp;
      for(int i=1;i<=sz;i++)
      {
           if(node[i].cc>=2)
           {
               hh=(node[i].cc*(node[i].cc-1))/2;
               for(int i=1;i<=hh;i++)
               Q.push(0);         
           }       
      } 
}
int ddd()
{

     //freopen("in.txt","r",stdin);
     //freopen("out.txt","w",stdout);
     // freopen("link.in","r",stdin);freopen("link.out","w",stdout);
      bb[0]=1;
      for(int i=1;i<=30;i++)
      bb[i]=(1<<i);
      int n,k,zz,nn,tt;
      scanf("%d%d",&n,&k);
      root=newnode();
      nn=n;
      while(nn--)
      {
            char s[60];
            scanf("%d",&zz);
            //cout<<zz<<endl;
            tt=zz;
            for(int i=0;i<31;i++)
            {
                  if(tt&bb[30-i])
                  {
                   s[i]='1';
                   tt-=bb[30-i];
                  }
                  else
                  s[i]='0';
                  if(tt==0)
                  {
                     s[i+1]=0;
                     break;         
                  } 
            } 
           insert(s,zz);
      }
      sfind();
      int hh;
      for(int i=30;i>=0;i--)
      {
           zz=0;
           for(int j=1;j<=f[i][0];j++)
           {
              hh=node[f[i][j]].z;
              zz+=(hh*(hh-1))/2;      
           }
           if(zz>=k)
           {
              zz=i;
             break;         
           }
      }//return 0;
      ds=zz;
      for(int i=1;i<=f[zz][0];i++)
      if(node[f[zz][i]].z>1)
      {
        dfs(&node[f[zz][i]]); 
       for(int p=1;p<=g[0];p++)
         for(int j=p+1;j<=g[0];j++)
         if(g[p]!=g[j])
         Q.push(g[p]^g[j]);
         g[0]=0;
      }

       int uu=0;
       while(!Q.empty())
       {
         uu++;
         if(uu==k)
         {
           cout<<Q.top();
           break;
         }
         printf("%d ",Q.top());
         Q.pop();                 
      }
  return 0;   

}
int sss=ddd();
int main()
{ ;}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值