将所有 ai 插入到 01Trie 中,统计每一个子树下串的总数。从高到低枚举 k 和所有 ai 的每一位。
若 k 这一位为1,且所有 ai 这一位为1的多,则 x 这一位设置为1,ans 加入 ai 这一位为1的数量,否则设为0,ans 加入 ai 这一位为0的数量。
若 k 这一位为0,且所有 ai 这一位为1的多,则 x 这一位设置为1,舍弃 ai 这一位为0的,否则设为0,舍弃 ai 这一位为1的。
为什么这个做法只能通过样例和 #8#9 两个点?求 Hack 和正解。
#include <cstdio>
using namespace std;
const int N=10485760;
const int L=19;
struct Node
{
int ch[2],cnt;
}t[N];
char buf[1<<20],*p1,*p2;
int len=1,ans=0,n,k;
inline char gc()
{
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==buf?EOF:*p1++;
}
inline void read(int &x)
{
char c;
while((c=gc())<'0'||c>'9');
for(x=c^48;(c=gc())>='0'&&c<='9';x=(x<<3)+(x<<1)+(c^48));
}
inline void insert(int x)
{
int cur=1,bit;
for(int i=L;i>=0;--i)
{
++t[cur].cnt;
bit=x>>i&1;
if(!t[cur].ch[bit]) t[cur].ch[bit]=++len;
cur=t[cur].ch[bit];
}
++t[cur].cnt;
}
inline void getans()
{
int cur=1,bit,l,r;
for(int i=L;i>=0;--i)
{
bit=k>>i&1;
l=t[cur].ch[0];
r=t[cur].ch[1];
if(bit)
{
if(t[l].cnt>t[r].cnt)
{
ans+=t[l].cnt;
cur=r;
}
else
{
ans+=t[r].cnt;
cur=l;
}
}
else
{
if(t[l].cnt>t[r].cnt) cur=l;
else cur=r;
}
}
}
int main()
{
int x;
read(n),read(k);
while(n--)
{
read(x);
insert(x);
}
getans();
printf("%d",ans);
return 0;
}