题目

传送门 to LOJ

思路

这篇博客讲得很好。我只做一些简要说明。

子任务一:求 min ⁡ \min min 值。这个其实就是卡常的常识,位运算消除分支。而且,如果你看过 O 2 \rm O2 O2 编译下的汇编代码,你会发现 O 2 \rm O2 O2 也是这样干的。

只需要取出 ( a − b ) (a-b) (a−b) 的符号位,用它填满 k k k 个比特。用代码实现,填满方式是 ( ∼ s ) + 1 (\sim s)+1 (∼s)+1,即 s s s 按位取反后再加 1 1 1 。它实际上就是取相反数。而 O 2 \rm O2 O2 的实现就比较粗暴了,因为汇编右移指令会自动用符号位填充高位……

填满之后,分别与 a , b a,b a,b 取按位与,二者求异或和。因为二者之一会是零,另一个会不变。

而操作次数只有 O ( log ⁡ n ) \mathcal O(\log n) O(logn),我们需要考虑 并行。因为对寄存器右移,实际上等价于对多个数同时右移。简单的想法是后一半跟前一半比较,但是这样会导致 “符号位” 没有空间;所以我们用奇数位和偶数位比较。

怎样得到 ( a − b ) (a-b) (a−b) 呢?先将 b b b 按位取反,再做加法。同时,我们会很高兴地发现,此时 “符号位” 已经是 k k k 个 0 0 0 或 1 1 1 了,类似于汇编的右移指令!直接右移即可。

子任务二:排序。这个就比较复杂了,一方面我们没有条件语句,另一方面我们要保持 O ( n ) \mathcal O(n) O(n) 的操作数。

没有条件语句,归并排序和快速排序就嗝屁了。冒泡是可行的,需要并行,并行的结果就是 奇偶移项排序:考虑奇数位与后面的数交换,考虑偶数位与后面的数交换,重复该过程。这个 i d e a \rm idea idea 在某场 CF \textrm{CF} CF 考过,当时需要算,多少轮(上面描述了两轮的情况)能够完成排序。答案不超过 n n n 轮,证明从略。

上面已经可以通过了,但我们还有一个更强的做法是,奇偶归并排序。这是 in-place merge sort \text{in-place merge sort} in-place merge sort 的一种,正常时间复杂度是 O ( n log ⁡ 2 n ) \mathcal O(n\log^2 n) O(nlog2n) 。归并还是要归并,即两边先递归。重点在于, in-place \text{in-place} in-place 合并两个有序数列。不妨设 n n n 为 2 2 2 的幂。

首先,将奇数位数字取出,然后 in-place \text{in-place} in-place 合并。同理,将偶数位也 in-place \text{in-place} in-place 合并。而后,只需要考虑每个偶数位的数字与后一个数字交换即可。

证明:在合并序列前,对于每个偶数位的数字,它前面的数字都小于自己(因为两个子数列都有序)。所以,递归合并后,对于第 k k k 大的偶数位的数字,至少有 k k k 个奇数位的数字小于自己,即第 k k k 大的奇数位数字小于该数。另一方面,除了两个子数列的首元素,奇数位数字前也有小于自己的偶数位元素。所以第 k k k 大的偶数位数字小于 ( k + 2 ) (k{\rm+}2) (k+2) 大的奇数位数字。

于是,第 k k k 大的偶数位数字,只需要跟第 ( k + 1 ) (k{\rm+}1) (k+1) 大的奇数位数字比较。这个数字就是它后面那个数。证毕。复杂度 T m ( n ) = 2 T m ( n 2 ) + O ( n ) = O ( n log ⁡ n ) T_m(n)=2T_m({n\over 2})+\mathcal O(n)=\mathcal O(n\log n) Tm​(n)=2Tm​(2n​)+O(n)=O(nlogn) 。

合并是 O ( n log ⁡ n ) \mathcal O(n\log n) O(nlogn) 的,总复杂度就是 O ( n log ⁡ 2 n ) \mathcal O(n\log^2n) O(nlog2n) 。但是在本题中,并行的能力是很强的,只要比较的元素之间等距,就可以并行。对奇数位合并,和对偶数位合并,二者可以直接并行,所以合并操作次数是 T m ( n ) = T m ( n 2 ) + O ( 1 ) = O ( log ⁡ n ) T_m(n)=T_m({n\over 2})+\mathcal O(1)=\mathcal O(\log n) Tm​(n)=Tm​(2n​)+O(1)=O(logn),同理递归左右子数列进行排序也可并行,复杂度 T ( n ) = T ( n 2 ) + T m ( n ) = O ( log ⁡ 2 n ) T(n)=T({n\over 2})+T_m(n)=\mathcal O(\log^2 n) T(n)=T(2n​)+Tm​(n)=O(log2n),实乃壮举!

代码

本题的限制较为宽松,选择容易实现的方法即可。

#include "registers.h"
#include <vector>
using namespace std;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)const int m = 100, b = 2000;
vector<bool> mask;
void memset(vector<bool>::iterator it,bool val,int len){for(; len; --len,++it) *it = val; // similar to pointer
}
void construct_instructions(int s, int n, int k, int q){mask.resize(b); // and never changememset(mask.begin(),false,b); // clearif(s == 0){ // I hate melded 2 questionsif(n&(n-1)){ // not power of 2memset(mask.begin()+n*k,true,(128-n)*k), n = 128;append_store(1,mask), append_or(0,0,1);}for(int len=1; len!=n; len<<=1){memset(mask.begin(),false,n*k);for(int i=0; i!=n; i+=(len<<1))memset(mask.begin()+(i+len)*k,true,k);append_store(1,mask), append_and(2,0,1);append_xor(0,0,2); // remove odd numbersappend_right(2,2,len*k); // align odd and even numbersappend_not(3,2); // negate odd numbersappend_add(4,0,3); // add to get signappend_right(4,4,k); // fill number with signappend_and(0,0,4); // if sign = 1, then a is smallerappend_not(4,4); append_and(2,2,4); // else b <= aappend_xor(0,0,2); // one of them is empty}}if(s == 1){ // difficult sortif(n&1){ // assume even elementsmemset(mask.begin()+n*k,true,k);append_store(1,mask), append_or(0,0,1);memset(mask.begin()+n*k,false,k), ++ n;}memset(mask.begin(),true,k);append_store(0xF,mask); // cover first elementmemset(mask.begin(),false,k);memset(mask.begin()+(n-1)*k,true,k);append_store(0xE,mask); // cover last elementrep(par,0,1){memset(mask.begin(),false,n*k);for(int i=(par^1)<<1; i!=n; i+=2)memset(mask.begin()+(i^par)*k,true,k);append_store(5+par,mask); // save mask}rep(cs,1,n) rep(par,0,1){append_and(2,0,5+par); // pre-computedappend_xor(0,0,2), append_right(2,2,k);if(!par) append_or(2,2,0xE); // INFTYappend_not(3,2), append_add(4,0,3), append_right(4,4,k);if(!par) append_or(4,4,0xF); // cover first elementappend_and(0xA,0,4); // if sign = 1, then a is smallerappend_not(4,4); append_and(0xB,2,4); // else b <= aappend_xor(0xC,0,2); // original xor valueappend_xor(0,0xA,0xB); // one of them is emptyappend_xor(0xC,0xC,0); // get another oneappend_left(0xC,0xC,k), append_xor(0,0,0xC);}}
}

后记

谁告诉你 bool[] v 表示 vector<bool> v 的?我本以为这只是误用了 java-style \text{java-style} java-style 呢……

[IOI2021]位移寄存器相关推荐

  1. 一种基于线性反馈位移寄存器的随机数生成方法

    以下介绍一种基于线性反馈位移寄存器的随机数生成方法,这种算法是某品牌MCU主控的随机数模块生成算法,主控上是电路直接实现的,产生随机数的速度很快,用C代码描述如下: #define WORD unsi ...

  2. 转录因子功能域预测数据库_使用内置转录功能的Microsoft Word节省时间

    转录因子功能域预测数据库 Thanks to a powerful new productivity enhancement, Microsoft 365 subscribers can now tr ...

  3. 寄存器与移位寄存器(数字电路)

    目录 寄存器的功能: 基本构成: 寄存器分类 移位寄存器 移位寄存器按功能分类 四位双向位移寄存器74194 移位寄存器的具体应用 1.环形计数器 2.扭环形计数器 3.一般位移型计数器 4.偶.奇数 ...

  4. 计算机系统基础期中考试,计算机系统基础第二次作业.docx

    文档介绍: 计算机系统基础第二次作业3.对于以下AT&T格式汇编指令,根据操作数的长度确定对应指令助记符中的长度后缀,并说明每个操作数的寻址方式.(1)mov8(%ebp,%ebx,4),%a ...

  5. 计算机系统-电路设计07-上升沿D触发器的内部电路实现/移位寄存器/串行接口/并行接口

    D是英文Data的意思 之前的文章介绍了RS触发器的内部电路实现,该电路有个缺点,就是需要用R和S两个控制端输入,才能控制Q端的输出,为了减少复杂度,D触发器诞生了,D触发器通过一个输入端,控制一个输 ...

  6. 51单片机基于Proteus的8X8点阵滚动显示心形

    代码及仿真原理图下载地址: https://download.csdn.net/download/qq_41639829/10641349 一.效果展示及连线方式 注:制作动图时效果显示不好 二.所用 ...

  7. 详细介绍GPIO、I2C、SPI通讯原理以及物理层原理

    目录 一. GPIO 1. 什么是GPIO? 2. GPIO组成原理 3. GPIO工作原理 二. I2C 1. 什么是I2C? 2. I2C组成原理 3. I2C的特性 4. I2C的通讯模式 5. ...

  8. matlab产生均匀白噪声,各种分布白噪声的产生matlab.pdf

    各种分布白噪声的产生matlab 3.各种分布白噪声的产生 均匀分布白噪声的产生 1.物理方法 2.数学方法 线性同余法.联合法.反馈位移寄存器法 非均匀分布白噪声的产生 1.理论方法 反变换法. ...

  9. MicroPython-On-ESP8266——数码管的使用,2片HC595驱动四位数码管

    MicroPython-On-ESP8266--数码管的使用,2片HC595驱动四位数码管 1. 背景 前面在使用四位数码管时,需要用来12个GPIO接口,结果咱micropython能驱动的esp8 ...

最新文章

  1. php 原生开发,四个优秀php原生开发实战视频教程推荐(必学)
  2. hive加载大文件(3G)
  3. javascript 一些小常用的技巧
  4. 我是这样理解HTTP和HTTPS区别的
  5. (开源)XMind2TestCase一个高效的测试用例设计解决方案
  6. css为什么要用浮动_CSS中有几种定位?如何使用?
  7. android刷机工具mac版,苹果一键刷安卓!OS X版CM刷机工具发布
  8. matlab多元函数拟合,只有数据,不知道函数形式,未知函数关系的多元函数拟合
  9. web前端基础案例-开发QQ空间旋转时光轴
  10. openedge-function模块浅析——百度BIE边缘侧openedge项目源码阅读(3)
  11. 朝着先能干活的方向努力。。。奥利给!!!06
  12. | 名师博客 | 地址 |
  13. python 列表 元祖_Python_列表与元祖
  14. mysql表名备注_「备注」mysql添加备注信息 - seo实验室
  15. pod spec的创建及其使用
  16. 首先实现立即执行轮询函数,然后setInterval再间隔执行轮询函数,实现方法
  17. Java操作数据库方式五MyBatis使用入门
  18. 绿色版eclipse
  19. Educoder- 《JAVA从小白到大牛》(第二章)2-3 Java面向对象 - 封装、继承和多态的综合练习
  20. 一个简单的抽奖箱抽幸运会员脚本

热门文章

  1. 深度学习硬啃计划与笔记
  2. SAM9X5替换系统启动时米尔科技的Logo进度条
  3. 影像组学训练营 第一天(共三天)
  4. 聊聊海外主流支付方式
  5. kali linux修改主机名,CentOS-7修改主机名
  6. MySQL常用命令学习笔记
  7. 如何用matlab编写分段函数_请教各位怎样用matlab定义一个分段函数MATLAB分段函数...
  8. Ribbon的重试机制
  9. 2018_WWW_Dual Graph Convolutional Networks for Graph-Based Semi-Supervised Classification
  10. UE4 初始化全局着色器库所需的游戏文件缺失