ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[loj3528]位移寄存器

2021-07-14 09:03:03  阅读:163  来源: 互联网

标签:... lceil .. min loj3528 位移 寄存器 rceil append


当$s=0$时(求最小值):

若$x_{0},x_{1},...,x_{n-1}$和$y_{0},y_{1},...,y_{n-1}$像题中所给的方式存储在$r[0][0..nk-1]$和$r[1][0..nk-1]$,那么执行

not(2,1),add(2,0,2),xor(2,0,2),xor(2,1,2),right(2,2,k)
store(3,[1,0,0,...,0,1,0,0,...,0,......]),and(2,2,3)
left(3,2,1),or(2,2,3)
left(3,2,2),or(2,2,3)
……
left(3,2,2^{L-2}),or(2,2,3)
left(3,2,k-2^{L-1}),or(2,2,3)
not(3,2),and(2,0,2),and(3,1,3),or(0,2,3)

(其中第2行$store$中1的位置为所有$k$的倍数,第7行$L=\lceil\log_{2}k\rceil$)

即可将$\min(x_{i},y_{i})$像题中所给的方式存储在$r[0][0..nk-1]$

操作次数为$2L+11$,预处理第二步$store$,当$k=10$时为$18+1$(后者的1指全局)

由此进行分治,即每一次将前$\lceil\frac{n}{2}\rceil$个和后$\lceil\frac{n}{2}\rceil$个取$\min$使得$n'=\lceil\frac{n}{2}\rceil$,直至$n=1$即为答案

操作次数为$19\lceil\log_{2}n\rceil+1$,当$n=100$时为134,可以通过

 

当$s=1$时(排序):

类似前面取$\min$,我们可以构造"检查-交换"操作,只需要将最后一行修改为

not(3,2),and(4,0,2),and(5,1,3),and(6,0,3),and(7,1,2),or(0,4,5),or(1,6,7)

即可将$\min(x_{i},y_{i})$存储在$r[0][0...nk-1]$,将$\max(x_{i},y_{i})$存储在$r[1][0..nk-1]$

操作次数为$2L+14$,预处理第二步$store$,当$k=10$时为21+1

由于要先确定交换的位置(而不是根据数值交换),那么通常的排序算法中只有冒泡和选择可以支持,但两者的交换次数都为$o(n^{2})$,无法通过

注意到上述过程支持同时交换多个不同的数,此时有一个更为优秀的奇偶移项排序,伪代码如下:

i=1..(n+1)/2
    j=1..n/2 swap(a[2j-1],a[2j])
    j=1..(n-1)/2 swap(a[2j],a[2j+1])

(其中$a_{i}$下标从1到$n$,/2都指下取整,swap指"检查-交换"操作)

两次$j$的循环,实际上都可以用一次交换代替,那么交换次数即降为$o(n)$

具体实现,只需要将奇数位和偶数位分别取出,并且高位要补0避免0被交换到较小处

操作次数为$48\lceil\frac{n+1}{2}\rceil+5$,当$n=100$时为2405,可以通过

 1 #include<bits/stdc++.h>
 2 #include"registers.h"
 3 using namespace std;
 4 #define B 2000
 5 int n,k,L;
 6 void get_min(){
 7     append_not(2,1);
 8     append_add(2,0,2);
 9     append_xor(2,0,2);
10     append_xor(2,1,2);
11     append_right(2,2,k);
12     append_and(2,2,99);
13     for(int i=0;i<L-1;i++){
14         append_left(3,2,(1<<i));
15         append_or(2,2,3);
16     }
17     if (L)append_left(3,2,k-(1<<L-1));
18     append_or(2,2,3);
19     append_not(3,2);
20     append_and(2,0,2);
21     append_and(3,1,3);
22     append_or(0,2,3);
23 }
24 void swap(int x,int y){
25     append_not(2,1);
26     append_add(2,0,2);
27     append_xor(2,0,2);
28     append_xor(2,1,2);
29     append_right(2,2,k);
30     append_and(2,2,99);
31     for(int i=0;i<L-1;i++){
32         append_left(3,2,(1<<i));
33         append_or(2,2,3);
34     }
35     if (L)append_left(3,2,k-(1<<L-1));
36     append_or(2,2,3);
37     append_not(3,2);
38     append_and(4,0,2);
39     append_and(5,1,3);
40     append_and(6,0,3);
41     append_and(7,1,2);
42     append_or(x,4,5);
43     append_or(y,6,7);
44 }
45 void calc0(){
46     for(;n>1;n=((n+1)>>1)){
47         append_right(1,0,(n>>1)*k);
48         get_min();
49     }
50 }
51 void calc1(){
52     vector<bool>v,v0,v1;
53     for(int i=0;i<B;i++)v.push_back((n*k<=i));
54     append_store(98,v);
55     append_or(0,0,98);
56     for(int i=0;i<B;i++)v0.push_back(((i/k)&1)^1);
57     for(int i=0;i<B;i++)v1.push_back(((i/k)&1));
58     append_store(96,v0);
59     append_store(97,v1);
60     for(int i=1;i<=((n+1)>>1);i++){
61         append_and(1,0,97);
62         append_right(1,1,k);
63         append_and(0,0,96);
64         swap(0,1);
65         append_left(1,1,(k<<1));
66         swap(1,0);
67         append_right(1,1,k);
68         append_or(0,0,1);
69     }
70 }
71 void construct_instructions(int p,int nn,int kk,int q){
72     n=nn,k=kk,L=0;
73     while ((1<<L)<k)L++;
74     vector<bool>v;
75     for(int i=0;i<B;i++)v.push_back(i%k==0);
76     append_store(99,v);
77     if (!p)calc0();
78     else calc1();
79 }
View Code

 

标签:...,lceil,..,min,loj3528,位移,寄存器,rceil,append
来源: https://www.cnblogs.com/PYWBKTDA/p/15009233.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有