题意
给你 个数和一个 ,每次你可以选一个数改变为这个数 。这个操作可以进行任意次,问至少将几个数进行与运算才能使得至少有两个数相等,注意:如果生产后的数和原来一样,那么只算一个。
思路
还是一道看上去很难的题,这道题我的思路非常非常的特殊。
要做这道题,我们首先要知道这些定理和结论:
一个数无论与另一个数进行与运算几次,得出的值都是一个数。
求最小的步数,只要我们满足有两个数想等了,那么就可以判断输出了。也就是说,只有 种情况: 。 为不可能, 为本来就有至少 个相等的, 为有一个数进行一次与运算后等于了一个在原序列出现过的数, 为有 个数进行与运算后等于了一个没有在原序列出现过的数。
如果一个数经过与运算后能得到自己,那就别进行运算。
根据上面两个加黑为要点,我们可以分类讨论。有 个坑,有的地方我会在代码里注释。
Code
#include<bits/stdc++.h>
using namespace std;
int n,x,ans=-1,a[100100],times[100100];
//times[i]=1代表本身与与运算后一样的一次,=2代表一个数进行了与运算产生了一个新的数
int main()
{
cin>>n>>x;
for(int i=1;i<=n;i++)//先处理自己本身不变的情况
{
cin>>a[i];
if (times[a[i]])
return cout<<0<<endl,0;
times[a[i]]=1; //出现过一次了
}
for(int i=1;i<=n;i++)//再处理进行与运算的情况
{
int b=a[i]&x;
if(times[b]==1&&a[i]!=b)//注意着里a[i]必须不能与b相等
return cout<<1<<endl,0;
else if(times[b]==0)
times[b]=2;
else if(times[b]==2)//如果可以2次完成题目要求,并不代表后面没有更优秀的解.
ans=2;
}
cout<<ans<<endl;
return 0;
}