2020-12-31

博客园Logo
首页
新闻
博问
专区
闪存
班级

代码改变世界
搜索
注册
登录
返回主页
TechFlow2019
博客园 首页 新随笔 联系 订阅 管理随笔 - 309 文章 - 0 评论 - 214
codeforces 1438D,思路非常非常巧妙的构造题
大家好,欢迎来到codeforces专题。

今天选择的问题是contest1438的D题,全场通过人数为1325人。一般在codeforces当中千人通过的题难度都不算太高,但是这题有点例外,虽然没有涉及一点高深的算法,但是想要自己做出来还是有点难度的。

题目链接:https://codeforces.com/contest/1438/problem/D

废话不多说了,我们直接来看题。

题意
给定一个拥有n()个正整数的数组,然后我们队数组当中的元素进行一种神奇的异或操作。

操作如下,我们选择三个不同的下标i、j、k。对a[i],a[j],a[k]这三个元素执行异或操作,即。之后这三个数分别赋值成这个异或之后的结果。

现在我们想要在n步这样的神奇异或操作之内让数组当中的所有元素全部相等,请问这一点是否可能呢?首先输出YES或NO,表示是否有解。如果有解输出需要操作的步数,以及对应选择的元素下标。

样例

在第一个样例当中,4、1、7的异或结果为2,所以通过这样一步操作之后,即可以满足所有元素全部均等。

题解
我一开始的时候惯性思维,既然是异或运算,那么肯定要从二进制下手。一个数组当中的所有元素均等,其实就等价于它们在每一个二进制位上也等相等,同为0或者是同为1。于是我就一直在思考怎么来针对每一个二进制位来进行判断和选择,不知不觉就走进了死胡同,因为这些二进制位之间彼此影响, 我们很难一位一位地梳理清楚。

我之所以走进死胡同是因为被题目当中的一个条件给欺骗了,这个条件就是最多n个操作步骤的限制。我们直观上都会觉得这是一个非常严苛的要求,所以会期望想到一个完美的解法,可以用最少的步骤解开这个问题。

但实际上这个n足够大,足够一些看起来非常笨的方法也能AC。不得不说这也是很多题目当中惯用的思维陷阱,考验的就是选手的胆量和经验。

异或的性质
首先我们来分析一下异或运算,这题当中并没有对异或做什么特殊的处理。唯一不同的地方就是,我们是对三个数进行异或。我们从最基础的01二进制位来分析,3个数做异或只有四种情况。000、010、011和111,我们发现其中000和011的结果都是0,010和111的结果是1。因为异或相同为0,不同为1的计算特性,会导致相同的数被消除。

比如我们计算的三个数是[a,b,b]那么最后的结果是a,我们可以利用这一点来做文章。想起来或许有些复杂,但是说穿了真的一文不值。

我们假设n=7,这7个数分别是[a,b,c,d,e,f,g]。首先我们对前三个数进行异或操作,这样我们会得到:[h,h,h,d,e,f,g],接着我们选择第3、4、5位的元素操作,得到:[h,h,j,j,j,f,g]。我们继续选择第5、6、7位的元素进行操作,得到[h,h,j,j,k,k,k]。

到这里其实已经有点眉目了,因为[a,b,b]的操作结果是a,我们剩下要做的就是继续选择,把除了k之外其他的元素全部消除。

我们继续选择第3、4、5位的元素操作,得到[h,h,k,k,k,k,k],同理我们最后选择第1、2、3位的元素操作,这样整个数组当中的元素都变成了k。到这里,我们一共进行了5次,也就是n-2次操作,完全没有超过题目的限制。

但是这里有一个小问题,这个方案之所以可行是有前提的。它最大的前提就是n是奇数。如果n是偶数,就会最后剩下一个元素,这个应该怎么解决呢?

偶数的情况
偶数的情况我们光想是很难想出办法来的,因为我们解决不了最后多余一个元素的问题。

这里需要用到一个关键性的推论,这个推论非常隐蔽,真的不容易想到。我们假设,当n为偶数时,那么无论我们对这n个元素如何操作,这个异或得到的k保持不变。

这个结论是从哪里来的?其实也是从异或的性质当中来的。我们对三个数做异或,从具体某一个二进制位来分析。我们会发现我们的操作不会改变整体这n个bit的奇偶性。对于异或操作而言,两两相消,最后的结果只和奇偶性相关。最终的结果只和这个奇偶性相关。

从这一点出发,我们进一步可以得到如果,那么一定无解。

这个结论其实也很简单,因为我们已经知道了,无论我们如何操作也不会改变这个k值。由于n是偶数,所以如果n个数完全相等的话,那么它们的异或值一定等于0,所以k不等于0的时候,一定无解。

当k等于0的时候怎么办呢?其实非常简单,我们只需要抛弃掉最后一个元素,把之前的n-1个元素按照上面n为奇数时的操作全部操作相等即可。这样一番操作之后,数组会变成这样[a,a,a,a…a,b]。前面n-1个a的异或值为a,而整体n个数的异或值为0,所以可以得到a=b。那么我们就完成了整个操作。

整个思路有了之后,代码实现就太简单了。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define rep(i,a,b) for (int i=a;i<b;i++)
#define Rep(i,a,b) for (int i=a;i>=b;i–)
#define foreach(e,x) for (__typeof(x.begin()) e=x.begin();e!=x.end();e++)
#define mid ((l+r)>>1)
#define lson (k<<1)
#define rson (k<<1|1)
#define MEM(a,x) memset(a,x,sizeof a)
#define L ch[r][0]
#define R ch[r][1]
const int N=100050;
const long long Mod=1000000007;

using namespace std;

int a[N];
int main() {
int n, x;
scanf("%d", &n);
rep(i, 0, n) {
scanf("%d", a + i);
}
// 如果n为奇数,一定有解
if (n % 2) {
puts(“YES”);
printf("%d\n", n-2);
for (int i = 0; i + 2 < n; i+=2) {
printf("%d %d %d\n", i+1, i+2, i+3);
}
for (int i = n-3; i - 2 >= 0; i-=2) {
printf("%d %d %d\n", i+1, i, i-1);
}
}else {
// 如果n为偶数,判断整个数组的异或值是否为0
x = 0;
rep(i, 0, n) x ^= a[i];
if (x > 0) {
puts(“NO”);
}else {
n --;
puts(“YES”);
printf("%d\n", n-2);
for (int i = 0; i + 2 < n; i+=2) {
printf("%d %d %d\n", i+1, i+2, i+3);
}
for (int i = n-3; i - 2 >= 0; i-=2) {
printf("%d %d %d\n", i+1, i, i-1);
}
}
}
return 0;
}
到这里,今天这道题就做完了,怎么样,今天的题目还挺有意思吧。讲道理把算法讲出来之后非常简单,几乎没有难度,但是如果让我们自己思考,会变得非常难,我们很难从当中整理出思绪来。思路巧妙有趣这也是codeforces题目的最大魅力所在,希望大家都能体会到算法的乐趣。

今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、关注、转发)

标签: 算法, 数据结构, codeforces
好文要顶 关注我 收藏该文
TechFlow2019
关注 - 0
粉丝 - 198
+加关注
0 0
« 上一篇: 80%的学校还在给新生上C语言,它们OUT了吗?
posted @ 2020-12-31 13:21 TechFlow2019 阅读(0) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
写给园友们的一封求助信
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】博客园x丝芙兰-圣诞特别活动:圣诞选礼,美力送递
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻

相关博文:
· Codeforces Round #608 (Div. 2) 题解
· Codeforces 1263A. Sweet Problem(思维题)
· Codeforces Round #603 (Div. 2) (题解)
· Codeforces Round #604 (Div. 2) (题解)
· Codeforces Round #608 (Div. 2) 题解
» 更多推荐…

最新 IT 新闻:
· 学霸君暴雷背后:行业畸形、分食“遗骸”、两极分化
· 美团取消支付宝渠道引发反垄断诉讼:是正常商业行为还是侵犯消费者选择?
· Google Doodle纪念民权活动家伊丽莎白·佩拉特罗维奇
· 索尼互动娱乐在新加坡成立新总部 强化东南亚运营
· 中国新冠病毒疫苗获批上市:符合条件群众实现应接尽接
» 更多新闻…
历史上的今天:
2019-12-31 线性代数精华2——逆矩阵的推导过程
公告

日拱一卒,功不唐捐
欢迎关注我的公众号:TechFlow

昵称: TechFlow2019
园龄: 1年
粉丝: 198
关注: 0
+加关注
< 2020年12月 >
日 一 二 三 四 五 六
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9
搜索

找找看

谷歌搜索
常用链接

我的随笔
我的评论
我的参与
最新评论
我的标签
我的标签

算法(97)
LeetCode(58)
机器学习基础(53)
python(45)
数据结构(40)
Python基础(20)
git(16)
go语言(14)
高等数学(14)
git教程(13)
更多
随笔分类

Go(15)
LeetCode题解(53)
Python(37)
spark(6)
大数据与分布式(10)
机器学习(45)
其他(2)
数学基础(16)
算法与数据结构(48)
随笔档案

2020年12月(17)
2020年11月(18)
2020年10月(22)
2020年9月(21)
2020年8月(22)
2020年7月(22)
2020年6月(29)
2020年5月(31)
2020年4月(36)
2020年3月(32)
2020年2月(28)
2020年1月(23)
2019年12月(8)
最新评论

  1. Re:80%的学校还在给新生上C语言,它们OUT了吗?
    @柒星丸子 你要是这行从业者,你可以去面试一下,看看人家需不需要这个技能…学深和学浅都是2码事…
    –小小咸鱼YwY

  2. Re:80%的学校还在给新生上C语言,它们OUT了吗?
    @柒星丸子 不是正常破解而已…黑产看你破解后做什么,例如茅台,不过人家难不在于加密而是风控…
    –小小咸鱼YwY

  3. Re:80%的学校还在给新生上C语言,它们OUT了吗?
    @小小咸鱼YwY @柒星丸子 拜托现在还是多少是h5页面…都是app 所以破解app就能不属于黑产了吗?…
    –柒星丸子

  4. Re:80%的学校还在给新生上C语言,它们OUT了吗?
    @柒星丸子 拜托现在还是多少是h5页面…都是app…
    –小小咸鱼YwY

  5. Re:80%的学校还在给新生上C语言,它们OUT了吗?
    @小小咸鱼YwY 别把你们黑产灰产说得这么正当…
    –柒星丸子
    阅读排行榜

  6. 大数据算法——布隆过滤器(11165)

  7. 在vscode中配置LeetCode插件,从此愉快地刷题(7225)

  8. 概率统计——三扇门游戏与贝叶斯定理(3896)

  9. 一半人写不出冒泡排序,你的同龄人都躺下了(3733)

  10. MySQL不香吗,为什么还要有noSQL?(3496)
    评论排行榜

  11. 一半人写不出冒泡排序,你的同龄人都躺下了(31)

  12. 大数据算法——布隆过滤器(29)

  13. 80%的学校还在给新生上C语言,它们OUT了吗?(25)

  14. MySQL不香吗,为什么还要有noSQL?(14)

  15. 随机数大家都会用,但是你知道生成随机数的算法吗?(9)
    推荐排行榜

  16. 大数据算法——布隆过滤器(45)

  17. MySQL不香吗,为什么还要有noSQL?(20)

  18. 一半人写不出冒泡排序,你的同龄人都躺下了(17)

  19. 从头搭建一个“微博”有多难(14)

  20. 80%的学校还在给新生上C语言,它们OUT了吗?(10)
    Copyright © 2020 TechFlow2019
    Powered by .NET 5.0 on Kubernetes

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值