【题目】C.Big Secret

【题意】给定数组b,求重排列b数组使其前缀异或和数组a单调递增。\(n \leq 10^5,1 \leq b_i \leq 2^{60}\)。

【算法】异或

为了拆位分析,先考虑一个简单的问题:已知一个合法b数组和一个数字"1",求数字”1“是否能插入?

容易发现,”1“插入的位置必须满足前面的数字中有偶数个奇数(可以是0个),因为这样前缀和才能比上一位多1,满足要求。

进一步的,已知一个有y个奇数的合法b数组和x个数字”1“,求数字”1“能否全部插入?

利用上面的结论,容易发现当x<=y+1时,只需要在最前面放一个”1“,然后每隔一个奇数放一个”1“就能满足要求(”1“本身也是奇数)。

而当x>y+1时,无解。

上面这个结论可以扩展,对于第k位,已知有y个第k位为0的数字的合法b数组,和x个第k位为1的在\([1,2^{k+1}-1]\)范围内的数字,求数字能否全部插入?

为什么这样扩展是正确的?一个数字能否插入其实只取决于它的最高的1。因为如果最高位异或变成0,无论低位如何都不合法。如果最高为异或变成1,无论低位如何都合法。

现在考虑做法,如何在插入时保证不跳过每次前缀和为偶数的情况?预处理v[i]表示最高的”1“在第i位的数字列表,从前往后依次确定答案,从低位到高位枚举合法的位数并且数字列表不空就插入,累加前缀和。从低到高枚举就能保证插入的数字的低位一定都是不能插入的,免得低位的”1“使得跳过了前缀和为偶数的情况。

复杂度\(O(60*n)\)。

本题的关键在于从将数字插入已有的合法数列的角度考虑。

#include<cstdio>
#include<vector>
#define ll long long
using namespace std;
vector<ll>v[70];
int n;ll ans[100010],cur=0;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
ll u;scanf("%lld",&u);
for(int j=60;j>=0;j--)if((u>>j)&1){v[j].push_back(u);break;}
}
for(int i=1;i<=n;i++){
bool ok=0;
for(int j=0;j<=60;j++)if(!(cur&(1ll<<j))&&!v[j].empty()){
cur^=(ans[i]=v[j].back());v[j].pop_back();ok=1;break;
}
if(!ok){puts("No");return 0;}
}
for(int i=1;i<=n;i++)printf("%lld ",ans[i]);
return 0;
}

【CodeForces】925 C.Big Secret 异或的更多相关文章

  1. codeforces 925 c big secret

    题意: 给你n个数,b[1],b[2],b[3].......,让你重新排列,使a[i]的值递增 a[i]和b的关系: a[i] = b[1]^b[2]^b[3]^....^b[i]; 首先说异或   ...

  2. Codeforces Round #539 (Div. 2) 异或 + dp

    https://codeforces.com/contest/1113/problem/C 题意 一个n个数字的数组a[],求有多少对l,r满足\(sum[l,mid]=sum[mid+1,r]\), ...

  3. Codeforces - 662A 思路巧妙的异或

    题意:给你\(n\)堆石子玩尼姆博弈,每堆石子可以是\(a_i\)也可以是\(b_i\),选择概率相等且每堆选择相互独立,求先手必胜(异或不为0)的概率 首先需要找出一种优雅的策略表示方法(利用异或的 ...

  4. Codeforces 1054D Changing Array 贪心+异或和

    题意 给一个长度为\(n\)的位数为\(k\)的整数数列\(a\),一次操作可将任意\(a_i\)取反,问经过任意次操作后最多有多少个区间异或和不为\(0\) 分析 求出前缀异或和,区间异或和为\(0 ...

  5. CodeForces.1174D.EhabandtheExpectedXORProblem(构造前缀异或和数组)

    题目链接 这道题比赛的时候没做出来,赛后补题的时候发现其实可以构造一个前缀异或和数组,然后根据初始化的第一个值进行填数,但是作为菜鸡的我虽然坚信自己的想法是正确的却想了很久也没有能够构造出来所谓的前缀 ...

  6. codeforces div2 603 D. Secret Passwords(并查集)

    题目链接:https://codeforces.com/contest/1263/problem/D 题意:有n个小写字符串代表n个密码,加入存在两个密码有共同的字母,那么说这两个密码可以认为是同一个 ...

  7. Codeforces 251D - Two Sets(异或方程组)

    题面传送门 题意: 你有一个可重集 \(S=\{a_1,a_2,\dots,a_n\}\),你要把它划分成两个可重集 \(S_1,S_2\) 使得 \(S\) 中每个元素都恰好属于 \(S_1\) 与 ...

  8. CodeForces 496B Secret Combination

    Secret Combination Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u ...

  9. Codecraft-17 and Codeforces Round #391 (Div. 1 + Div. 2, combined)D. Felicity's Big Secret Revealed

    题目连接:http://codeforces.com/contest/757/problem/D D. Felicity's Big Secret Revealed time limit per te ...

随机推荐

  1. bower配置私服nexus3

    内容来自 https://help.sonatype.com/repomanager3/bower-repositories#BowerRepositories-BrowsingBowerReposi ...

  2. 微软职位内部推荐-Senior BSP Engineer

    微软近期Open的职位: The position of Sr. BSP engineer requires experience and good knowledge in mobile hardw ...

  3. Linux内核分析作业二

    贾瑗 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  一.操作系统是如 ...

  4. linux 常用命令-ps(process state)

    ps -ef | grep 端口号:查看某个端口的占用情况 ps -tunlp | grep 端口号:查看占用端口的进程名称

  5. 基于RYU的拓扑发现

    基于RYU的拓扑发现 前言 本次实验是一个基于RYU的拓扑发现功能.参考了呈神的实现方式,并加了一些自己实现方式,做了一些数据结构的改动. 数据结构 link_to_port 字典 有两种关系: 一是 ...

  6. 如何访问cxGrid控件过滤后的数据集

    var I: Integer; begin Memo1.Lines.Clear; with cxGrid1DBTableView1.DataController do for I := 0 to Fi ...

  7. webpack打包使用

    md创建文件夹 dir是遍历 如何安装node环境 首先下载安装包;安装好以后 使用cmd命令 建立一个新的文件夹(一定是英文的),然后cmd 命令中 cd 进入所安装的盘的地址. 在该文件夹下面 使 ...

  8. Windows 防火墙出站 入站规则简单说明

    1. Windows防火墙其实比linux的iptabels 要好用一些. 打开设置方式: 运行->输入control即可 选择系统和安全 2.win2019 以及改名字了 现在是 window ...

  9. 怎么判断pagecontrol下的TabSheet是否打开还是关闭求答案

    if pagecontrol.activepage=TabSheet1 then是在当前显示页------解决方案------------------------------------------- ...

  10. java 方法的返回类型

    定义了返回值类型后 必须要执行 return 因为 当一个变量初始化时候 需要有数据 如果方法体里面没有返回数据类型时 这个变量是没有数据的 会报错 所以必须要返回一个数据 当一个方法体里面有 if ...