Codeforces 1257 F Make Them Similar —— 哈希+折半状压

This way

题意:

现在有n个数,让你求一个数,让这些数异或上这个数,得到的新数组,每个数二进制下1的个数相同。

题解:

和我们这次新生校赛上的一道题目很像,解法都是相同的。
首先要想到将每一位分解出来,也就是第2的i次方这位取的话,对这些数的影响是什么,如果这一位上有的话,那么就是-1,否则+1.然后怎么将每个数都变成1个数相同的呢,我们只需要枚举0-30这些情况,然后检查我们异或之后是不是这个情况,很明显不能将每个数组存下来,需要用哈希存到map中。然后看每一位取不取的话,我们不能直接做,一因为这样是 2 30 2^{30} 种情况,一般出现这样子的情况的话,就是使用对半的方法。我们处理出前15位的情况,存到map中,然后做后15位的时候,对于每一种情况我都检查一遍0-30这些是否可能。

#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define pa pair<ull,ull>
int a[105],b[35][105],c[105];
map<pa,int>mp;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),c[i]=a[i];
    for(int i=0;i<30;i++){
        for(int j=1;j<=n;j++){
            if(a[j]&(1<<i))
                b[i][j]=-1;
            else
                b[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++)a[i]=__builtin_popcount(a[i]);
    for(int i=1;i<(1<<15);i++){
        pa h={0,0};
        int t[105]={0};
        for(int j=0;j<=14;j++){
            if(i&(1<<j))
                for(int k=1;k<=n;k++)
                    t[k]+=b[j][k];
        }
        for(int j=1;j<=n;j++)
            h={h.first*31ll+(ull)(28+t[j]),h.second*23ll+(ull)(28+t[j])};
        mp[h]=i;
    }
    mp[{0,0}]=0;
    int t[105];
    for(int i=0;i<(1<<15);i++){
        pa h={0,0};
        for(int j=1;j<=n;j++)t[j]=a[j];
        for(int j=0;j<=14;j++){
            if(i&(1<<j))
                for(int k=1;k<=n;k++)
                    t[k]+=b[j+15][k];
        }
        for(int bit=0;bit<=30;bit++){
            h={0,0};
            for(int j=1;j<=n;j++)
                h={h.first*31ll+(ull)(28ll+bit-t[j]),h.second*23ll+(ull)(28ll+bit-t[j])};
            if(mp.count(h)){
                int pre=mp[h],aft=i;
                int ans=pre+(aft<<15);
                
                printf("%d\n",ans);
                //for(int i=1;i<=n;i++)
                    //printf("%d%c",__builtin_popcount(ans^c[i])," \n"[i==n]);
                return 0;
            }
        }
    }
    printf("-1\n");
    return 0;
}
/*
3
324994 321920 371974
*/

发布了530 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/104101551