您的位置:首页 > 其它

3689

2016-07-15 20:28 447 查看
这道题方法挺神奇的。我们考虑比较小的是什么情况。。显然是在前几位进行了(自交。。。)然后就有一个非常奇奇怪怪的做法。枚举层数。看看每一层自交之后能产生多少数字当某一层自交产生的数小于k的时候。那么就把它上一层自交能产生的所有数字都排个序。然后取前k个即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 100000000
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,num;
int a[100005],b[1000005];
int bin[35],tmp[35][100005];
ll cnt[35];

void cal(int l,int r,int k)
{
if(l>=r)return;
int tot=0;
for(int i=l;i<=r;i++)
if(tmp[k+1][i]&bin[k])tot++;
int L=l-1,R=l+tot-1;
for(int i=l;i<=r;i++)
if(tmp[k+1][i]&bin[k])tmp[k][++L]=tmp[k+1][i];
else tmp[k][++R]=tmp[k+1][i];
if(k!=0){cal(l,l+tot-1,k-1);cal(l+tot,r,k-1);}
cnt[k]+=(ll)(r-l+1)*(r-l)/2;
}
void print(int l,int r,int k,int x)
{
if(l>=r)return;
if(k==x)
{
for(int i=l;i<=r;i++)
for(int j=i+1;j<=r;j++)
b[++num]=tmp[x+1][i]^tmp[x+1][j];
return;
}
int tot=0;
for(int i=l;i<=r;i++)
if(tmp[k+1][i]&bin[k])tot++;
if(k!=0){print(l,l+tot-1,k-1,x);print(l+tot,r,k-1,x);}
}
void solve2()
{
for(int i=1;i<=n;i++)tmp[31][i]=a[i];
cal(1,n,30);
bool flag=0;
for(int i=30;i>=0;i--)
if(cnt[i]<m){print(1,n,30,i+1);flag=1;break;}
if(!flag)print(1,n,30,0);
sort(b+1,b+num+1);
for(int i=1;i<=m;i++)
printf("%d",b[i]);
}
int main()
{
freopen("bb.in","r",stdin);
freopen("bb.out","w",stdout);
bin[0]=1;for(int i=1;i<=31;i++)bin[i]=bin[i-1]*2;
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();

solve2();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: