题意

现在我们想要在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 <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
#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为偶数,判断整个数组的异或值是否为0x = 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题目的最大魅力所在,希望大家都能体会到算法的乐趣。

牛客网-数据结构笔试题目(四)-Powerful Ksenia问题解决方案(附源码)相关推荐

  1. 牛客网-数据结构笔试题目(一)-猫咪特征提取思路解析(附源码)

    题意 小明是一名算法工程师,同时也是一名铲屎官.某天,他突发奇想,想从猫咪的视频里挖掘一些猫咪的运动信息.为了提取运动信息,他需要从视频的每一帧提取"猫咪特征".一个猫咪特征是一个 ...

  2. 牛客网-数据结构笔试题目(七)-k-amazing数字求解

    题意 给定n个数构成的数字,我们定义一个k-amazing数的概念.如果数a同时出现在数组中所有k个连续元素构成的序列当中,并且a是其中最小的那个,那么就称为a是一个k-amazing数字. 我们抽象 ...

  3. 牛客网-数据结构笔试题目(八)-离子能力跃迁问题求解

    题意 有一个人在玩一个离子激活的游戏,题目的背景是模拟的化学当中的离子能量跃迁.在化学当中,离子吸收能量可以从低能态跃迁到高能态,并且放出一定的能量. 现在有N粒离子排成一排(下标1-N),每一个离子 ...

  4. 牛客网-数据结构笔试题目(五)-动态规划问题求解

    题意 给定n个整数,对于这n个整数我们可以采取两种操作.第一种操作是在数组左侧选择连续的k个整数减1,第二种操作是选择右侧的连续k个整数减1. 比如假设数组是[3, 2, 2, 1, 4],比如我们选 ...

  5. 牛客网-数据结构笔试题目(三)-博弈论圆圈游戏(Circle Game)(附源码)

    题意 从前有两个人,一个叫Utkarsh,另外一个叫Ashish. 这两个人在一个2D的棋盘上玩移动棋子的游戏,一开始从原点出发,Ashish先手.每次可以把棋子向上或者是向右移动k个单位的距离.两人 ...

  6. 牛客网-数据结构笔试题目(二)-万万没想到之抓捕孔连顺思路解析(附源码)

    题意 我叫王大锤,是一名特工.我刚刚接到任务:在字节跳动大街进行埋伏,抓捕恐怖分子孔连顺.和我一起行动的还有另外两名特工,我提议 我们在字节跳动大街的N个建筑中选定3个埋伏地点. 为了相互照应,我们决 ...

  7. 牛客网-数据结构笔试题目(六)-最近点对问题求解思路

    题意 我们先来看下题意吧,题意很简单,在一个平面当中分布着n个点.现在我们知道这n个点的坐标,要求找出这n个点当中距离最近的两个点的间距. 分治法 如果我们仔细思考一下,会发现这个问题和排序其实非常类 ...

  8. 牛客网校招题题目收集----数据结构与算法篇

    选择题 a,b,c,d,e 对应出现的频率为4,6,11,13,15:以下符合哈夫曼编码的选项是?() A. a=000.b=01.c=001.d=10.e=11 B. a=000.b=001.c=0 ...

  9. 牛客网C语言题目练习

    牛客网C语言专题练习 BC1 实践出真知 BC2 我是大V BC3 有容乃大 BC6 小飞机 BC7 缩短二进制 BC8 十六进制转十进制 BC9 十六进制转十进制 BC11 学生基本信息输入输出 B ...

最新文章

  1. 使用RMAN恢复数据库
  2. 到底什么是面向对象,面试中怎么回答。面向过程和面向对象的区别是什么。java跨平台特性以及java和C++的区别。面向对象的三大特性——封装、继承和多态。面向对象的高拓展性以及低耦合度怎么体现?
  3. 《那些年啊,那些事——一个程序员的奋斗史》——111
  4. 银角大王 python_小猿圈python学习-细讲数据类型-列表
  5. oracle回退脚本怎么写_直播间脚本要怎么写?李佳琦、薇娅直播间直播脚本解析!...
  6. 求序列第K大算法总结
  7. 谈谈Angular关于$watch,$apply 以及 $digest的工作原理
  8. 新浪微博iOS版SDK“宝玉XP”框架学习笔记
  9. 苹果企业证书_IOS福利9月15日苹果企业证书已更新!重新下载即可!
  10. MongoDB数据库CXX Driver编译
  11. 第 37 章 ACOS - CLI
  12. 编程通用知识 字符编码(ascii,unicode,utf-8)
  13. 【转贴】ListView控件学习系列2-编辑ListView
  14. C++进阶之函数模板
  15. 【转】Monkey测试3——Monkey测试结果分析
  16. 微型计算机与接口技术总结,微机原理与接口技术课程总结
  17. 零基础学习SQL Server(一)---查询语句在项目实例中的执行
  18. MYSQL将两张表的数据合并显示
  19. windows背景豆沙绿设置
  20. Java 中XO 的概念

热门文章

  1. 工业级以太网交换机-管理型
  2. 【渝粤教育】国家开放大学2018年秋季 0341-21T高级英语听力(2) 参考试题
  3. 【渝粤教育】国家开放大学2018年春季 0508-21T影视特技及后期合成 参考试题
  4. [渝粤教育] 中国地质大学 企业文化建设与管理 复习题
  5. [渝粤教育] 西南科技大学 工程建设监理 在线考试复习资料
  6. 【渝粤教育】广东开放大学 房屋建筑学 形成性考核 (50)
  7. 国家开放大学2021春1295社会心理学(本)题目
  8. flutter 返回指定界面_Flutter页面路由导航及传参
  9. 网络演算(Networkcalculus)
  10. 域名是如何被墙的_如何快速搭建属于自己的个性网站?