Codeforces Round #500 (Div. 2) B And

题意

给你 N 个数和一个 X ,每次你可以选一个数改变为这个数 A n d X 。这个操作可以进行任意次,问至少将几个数进行与运算才能使得至少有两个数相等,注意:如果生产后的数和原来一样,那么只算一个。

思路

还是一道看上去很难的题,这道题我的思路非常非常的特殊。

要做这道题,我们首先要知道这些定理和结论:

  • 一个数无论与另一个数进行与运算几次,得出的值都是一个数。

  • 求最小的步数,只要我们满足有两个数想等了,那么就可以判断输出了。也就是说,只有 4 种情况: 1 , 0 , 1 , 2 1 为不可能, 0 为本来就有至少 2 个相等的, 1 为有一个数进行一次与运算后等于了一个在原序列出现过的数, 2 为有 2 个数进行与运算后等于了一个没有在原序列出现过的数。

  • 如果一个数经过与运算后能得到自己,那就别进行运算。

根据上面两个加黑为要点,我们可以分类讨论。有 2 个坑,有的地方我会在代码里注释。

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;
} 

猜你喜欢

转载自blog.csdn.net/qq_39984146/article/details/81319449