zoukankan      html  css  js  c++  java
  • F. Make Them Similar

    题目链接:

    题意:给出一个有n个数的数组a,问是否能找到一个x满足b[i]=a[i]^x。而这个b数组里面所有元素的二进制1的个数都是相等的

    a[i]<(2^30)-1  

    思路:

    由数据范围可知,x的范围一定在2^30内,那么我们很容易想到meet in the middle !!!对于30位的搜索折半复杂度为2^15随随便便就能AC啦(硬是WA了4发,还写了巨长时间emmm)

    首先我们预处理出前15位的状态,然后跟a数组全部元素做异或操作,那么对于15位后的我们可以取模去掉防止造成影响。

    然后我们能得到当前状态异或前15位得到的每个新的元素的1的个数,那么我们统计一下后一位减当前位的差值(为什么这样我一会再说)

    那么标记这个 vector数组,这个开个map就行了,顺便还能把当前状态放进去

    那么之后就是枚举后15位了,同理我们能得到一个后15位的数组,对于这个数组我们用当前位减去后一位。

    那么对于两个互补的数组,他们存在一个关系,一个用后一位减当前位,一个用当前位减后一位,得到的数组会是相同的。

    证明其实也不难想:如果他们是互补的,那么他们的顺序一定是相反的。所以就有这个条件!!!

    那么如果有满足这样的要求我们就可以得到答案了

    详情请见代码!

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define re register
    #define pb push_back
    #define fi first
    #define se second
    const int N=2e6+10;
    void read(int &a)
    {
        a=0;int d=1;char ch;
        while(ch=getchar(),ch>'9'||ch<'0')
            if(ch=='-')
                d=-1;
        a=ch^48;
        while(ch=getchar(),ch>='0'&&ch<='9')
            a=(a<<3)+(a<<1)+(ch^48);
        a*=d;
    }
    int a[N],n;
    vector <int> v;
    map <vector <int>,int> vis;
    int ans=-1;
    void dfs1(int i,int now)
    {
        if(i==15)
        {
            v.clear();
            for(re int j=1;j<=n;j++) v.pb(__builtin_popcount((now^a[j])%(1<<15)));
            for(re int j=1;j<n;j++) v[j-1]=v[j]-v[j-1];
            v.pop_back();
            if(!vis.count(v)) vis[v]=now;
            return;
        }
        dfs1(i+1,now);
        dfs1(i+1,now|(1<<i));
    }
    void dfs2(int i,int now)
    {
        if(i==15)
        {
            v.clear();
            for(re int j=1;j<=n;j++) v.pb(__builtin_popcount(now^(a[j]>>15)));
            for(re int j=1;j<n;j++) v[j-1]-=v[j];
            v.pop_back();
            if(vis.count(v)) ans=vis[v]|(now<<15);
            return;
        }
        dfs2(i+1,now);
        dfs2(i+1,now|(1<<i));
    }
    int main()
    {
        read(n);
        for(re int i=1;i<=n;i++) read(a[i]);
        dfs1(0,0);dfs2(0,0);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    1082 射击比赛 (20 分)
    1091 N-自守数 (15 分)
    1064 朋友数 (20 分)
    1031 查验身份证 (15 分)
    1028 人口普查 (20 分)
    1059 C语言竞赛 (20 分)
    1083 是否存在相等的差 (20 分)
    1077 互评成绩计算 (20 分)
    792. 高精度减法
    791. 高精度加法
  • 原文地址:https://www.cnblogs.com/acm1ruoji/p/11870284.html
Copyright © 2011-2022 走看看