Educational Codeforces Round 76 F 折半枚举

Educational Codeforces Round 76 F 折半枚举

https://codeforces.com/contest/1257/problem/F

题意:

数组a,找到一个x使得a中每一个元素异或x后“二进制中1的个数”相同。
数组长度100,数字大小2^30。

思路:

折半枚举答案X,如分为X前15位和后15位。之后我们再枚举期望的“相同个数”是多少,通过hash看看能不能满足就好了。

代码:

#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define PB push_back
#define LL long long
#define pii pair<int,int>
#define MEM(x,y) memset(x,y,sizeof(x))
#define bug(x) cout<<"debug "#x" is "<<x<<endl;
#define FIO ios::sync_with_stdio(false);
#define ALL(x) x.begin(),x.end()
#define LOG 20
const int inf =1e9;
const int maxn =3e5+7;
const int mod = 1e9+7;
const int N=3e5+7;
int n,m;
int a[maxn];

int main(){
    FIO;
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    map<vector<int>,int> hash_;
    const int mask=(1<<18)-1;
    for(int i=0;i<(1<<18);i++){
        vector<int> t(n);
        for(int j=0;j<n;j++){
            t[j]=__builtin_popcount((a[j]&mask)^i);
        }
        hash_[t]=i;
    }
    for(int i=0;i<(1<<12);i++){
        vector<int> t(n),p(n);
        int mx=0;
        for(int j=0;j<n;j++){
            t[j]=__builtin_popcount((a[j]>>18)^i);
            mx=max(t[j],mx);
        }
        for(int sum=mx;sum<=30;sum++){
            for(int j=0;j<n;j++){
                p[j]=sum-t[j];
            }
            if(hash_.count(p)){
                cout<<hash_[p]+(i<<18)<<endl;
                return 0;
            }
        }

    }
    cout<<"-1"<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/zhangxianlong/p/11865332.html

时间: 2024-12-18 01:18:09

Educational Codeforces Round 76 F 折半枚举的相关文章

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression 题意: 给你一个字符串,让你压缩,问压缩后最小的长度是多少. 压缩的形式为x(...)x(...)  x表示(...)这个出现的次数. 题解: 考虑dp[i]表示前i个字符压缩后的最小长度. 转移方程解释看代码,这里要用到kmp来找最小的循环节. 当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式. 这里我用的kmp找的循环节.复杂度严格n2. 1 #inclu

Educational Codeforces Round 21 F. Card Game(网络流之最大点权独立集)

题目链接:Educational Codeforces Round 21 F. Card Game 题意: 有n个卡片,每个卡片有三个值:p,c,l; 现在让你找一个最小的L,使得满足选出来的卡片l<=L,并且所有卡片的p的和不小于k. 选择卡片时有限制,任意两张卡片的c之和不能为质数. 题解: 和hdu 1565 方格取数(2)一样,都是求最大点权独立集. 不难看出来,这题再多一个二分. 注意的是在构造二部图的时候,按照c值的奇偶性构造. 当c==1时要单独处理,因为如果有多个c==1的卡片,

Educational Codeforces Round 76 (Rated for Div. 2) E. The Contest

Educational Codeforces Round 76 (Rated for Div. 2) E. The Contest(dp+线段树) 题目链接 题意: 给定3个人互不相同的多个数字,可以把数字移动给别人,问最少移动几次后可以使第一个人的数字为1~m1,第二个人m1~m2,第三个人m2~n(可以没有数字) 题解: 设c[1][i]为第一个人m1为i时需要移动的次数,c[3][i]为m2为i是第三个人需要操作的次数,当其他两个人数字合法时,第二个人的数字也会合法.枚举第一个人的每个i,

Educational Codeforces Round 24 F. Level Generation(三分)

题目链接:Educational Codeforces Round 24 F. Level Generation 题意: 给你n个点,让你构造ans条边,使得这ans条边中至少有一半是桥. 让你求ans的最大值. 题解: 首先我们将每一个点按顺序连起来,那么可以构成n-1个桥. 然后我们可以把其中的x个点拿出来连边,这些边都不是桥. x个点最多能连x*(x-1)条边,然后剩下的n-x个点连的边将会构成桥. 然后就可以构造一个函数关系,详见check函数,然后三分一下就行了. 1 #include

Educational Codeforces Round 14 - F (codeforces 691F)

题目链接:http://codeforces.com/problemset/problem/691/F 题目大意:给定n个数,再给m个询问,每个询问给一个p,求n个数中有多少对数的乘积≥p 数据范围:2≤n≤10^6, 1≤ai≤3*10^6,1≤m≤10^6, 1≤p≤3*10^6 解题思路:比赛的时候比较naive的思路是把n中的数字排序去了重之后,对于每个p,最多枚举√p步,就能得到答案.而这个naive的思路是O(p√p)的,结果T了. 后来百思不得其解,去看了官方的解答.感觉是一种很有

Educational Codeforces Round 28 F. Random Query

题意:一个数列,随机选l,r,f(l,r)为l,r区间内数的种数,问f(l,r)的期望 思路:sum(每个数算出他的贡献)/(n*n),我们这只考虑l<=r ,对于当前这数字他能贡献后面的所有区间,但是对于前面的话,他只共贡献到前一个相同的数后面 比如  1  2  3  4  2  5  6 对于第一个2  他贡献于  (1,2) (1,3)(1,4)(1,5)(1,6)(1,7) (2,2) (2,3)(2,4)(2,5)(2,6)(2,7) 对于第2个2  贡献于     (3,5)(3,

Educational Codeforces Round 72 F. Forced Online Queries Problem

题目梗概 有一张\(n\)个点的图,刚开始没有边,现在又两种操作,一种是加入一条边(如果这条边存在,否则删去这条边),一种是询问\(x,y\)是否联通. \(x,y\)给出的形式是\((x+last-1)%n+1\),\((y+last-1)%n+1\),\(last\)为上一次询问的答案. 解题思路 对于这题的离线版本有两种写法:线段树分治,以及对操作分块. 线段树分治的做法比较常见,下面来讲讲分块的做法. 对于当前块之前的操作,我们可以找出哪些边在当前块需要操作,设为集合\(B\),当然就有

Educational Codeforces Round 76 (Rated for Div. 2)

A - Two Rival Students 题意:共n个人排一排,两个人,位于a,b,相邻位置交换至多x次,最大化abs(a-b)的值. 题解:每次交换至多+1,不能超过n-1. #include<bits/stdc++.h> using namespace std; typedef long long ll; int main() { #ifdef KisekiPurin freopen("KisekiPurin.in", "r", stdin);