【CodeForces】925 C.Big Secret 异或
【题目】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 异或的更多相关文章
- 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]; 首先说异或 ...
- Codeforces Round #539 (Div. 2) 异或 + dp
https://codeforces.com/contest/1113/problem/C 题意 一个n个数字的数组a[],求有多少对l,r满足\(sum[l,mid]=sum[mid+1,r]\), ...
- Codeforces - 662A 思路巧妙的异或
题意:给你\(n\)堆石子玩尼姆博弈,每堆石子可以是\(a_i\)也可以是\(b_i\),选择概率相等且每堆选择相互独立,求先手必胜(异或不为0)的概率 首先需要找出一种优雅的策略表示方法(利用异或的 ...
- Codeforces 1054D Changing Array 贪心+异或和
题意 给一个长度为\(n\)的位数为\(k\)的整数数列\(a\),一次操作可将任意\(a_i\)取反,问经过任意次操作后最多有多少个区间异或和不为\(0\) 分析 求出前缀异或和,区间异或和为\(0 ...
- CodeForces.1174D.EhabandtheExpectedXORProblem(构造前缀异或和数组)
题目链接 这道题比赛的时候没做出来,赛后补题的时候发现其实可以构造一个前缀异或和数组,然后根据初始化的第一个值进行填数,但是作为菜鸡的我虽然坚信自己的想法是正确的却想了很久也没有能够构造出来所谓的前缀 ...
- codeforces div2 603 D. Secret Passwords(并查集)
题目链接:https://codeforces.com/contest/1263/problem/D 题意:有n个小写字符串代表n个密码,加入存在两个密码有共同的字母,那么说这两个密码可以认为是同一个 ...
- Codeforces 251D - Two Sets(异或方程组)
题面传送门 题意: 你有一个可重集 \(S=\{a_1,a_2,\dots,a_n\}\),你要把它划分成两个可重集 \(S_1,S_2\) 使得 \(S\) 中每个元素都恰好属于 \(S_1\) 与 ...
- CodeForces 496B Secret Combination
Secret Combination Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u ...
- 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 ...
随机推荐
- VLAN入门知识
版权声明: https://blog.csdn.net/xinyuan510214/article/details/52020987 本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载.但转 ...
- 访问kubernetes ingress-controller
ingress-controller可以理解为一套反向代理系统,本身需要暴露端口到集群外部,以便客户端访问. 根据实际使用,给出两种暴露端口的方式,如下: 方案一 拓扑 说明 ingress-cont ...
- B1030 完美数列 (25 分)
这是一道二分法的题目,许久不使用二分法,感觉有点生疏. #include<bits/stdc++.h> using namespace std; const int MAXN=100000 ...
- PAT甲题题解-1071. Speech Patterns (25)-找出现最多的单词
分割字符串的用法+map映射给出input中出现次数最多的单词,如果次数相同,给出按字典序最小的. 这里我用了自定义分隔符来读取字符串,方法如下: //按照定义的分隔符d来分割字符串,对str进行读取 ...
- PAT甲题题解-1088. Rational Arithmetic (20)-模拟分数计算
输入为两个分数,让你计算+,-,*,\四种结果,并且输出对应的式子,分数要按带分数的格式k a/b输出如果为负数,则带分数两边要有括号如果除数为0,则式子中的结果输出Inf模拟题最好自己动手实现,考验 ...
- LeetCode 633. Sum of Square Numbers平方数之和 (C++)
题目: Given a non-negative integer c, your task is to decide whether there're two integers a and b suc ...
- Daily Scrum NO.2
工作概况 符美潇(PM) 昨日完成的工作 1.Daily Scrum.日常会议及日常工作的分配和查收. 2.为两名团队新成员制定了任务并录入TFS. 今日工作 1.Daily Scrum.日常会议及日 ...
- 《Linux内核分析》第三周学习报告
<Linux内核分析>第三周学习报告 ——构造一个简单的Linux系统MenuOS 姓名:王玮怡 学号:201351 ...
- scrapy 爬虫怎么写入日志和保存信息
写入日志: 首先我的爬虫 name= article scrapy crawl article -s LOG_FILE=wiki.log 输出为不同格式: scrapy crawl article - ...
- <转>HTML、CSS、font-family:中文字体的英文名称
宋体 SimSun 黑体 SimHei 微软雅黑 Microsoft YaHei 微软正黑体 Microsoft JhengHei 新宋体 NSimSun 新细明体 PMingLiU 细明体 Ming ...