@description@

JOHNKRAM 最近在研究排序网络,但他发现他不会制作比较器,于是他用交换器来代替比较器。

一个交换器有两个输入端 x, y 和两个输出端 x′, y′​​。如果交换器处于关闭状态,则 x 收到的信号会从 x′ 发出,y 收到的信号会从 y′ 发出。如果交换器处于开启状态,则 x 收到的信号会从 y′ 发出,y 收到的信号会从 x' 发出。

JOHNKRAM 设计了这样一个递归定义的网络:

(1)1阶网络就是一个交换器。

(2)n (n>1) 阶网络的第一排是 2^(n−1) 个交换器,接下来是两个 n−1 阶网络,最后一排也是2^(n−1) 个交换器。

将第一排的输出端和第二排的输入端分别从左到右标号为 0∼2^n−1,第一排的 i 输出端连接到第二排的 i>>1 输入端,其中 >> 指n位二进制数的循环右移。

类似,将倒数第一排的输入端和倒数第二排的输出端分别从左到右标号为 0∼2^n−1,倒数第二排的 i 输出端连接到倒数第一排的 i<<1 输入端,其中 << 指 n 位二进制数的循环左移。

一个3阶的网络如下图所示:

JOHNKRAM 通过开关交换器来调整网络。现在他对一个 n 阶网络的 2^n 个输入端分别输入了一个数,第 i (0≤i<2^n) 个输入端输入的是 i。然后他给出了一个长度为 2^n 的排列 p。他希望你给出一种网络的状态,使得第 i (0≤i<2^n) 个输出端输出的是 pi。

input

包括不超过 10 组数据,每组数据包含两行。

第一行包含一个整数 n,其中 1≤n≤13。

第二行 2^n 个整数表示排列 p。

输入以 0 结尾。

output

如果无解,输出 -1。

否则输出 2n - 1 行,每行包含 2^(n-1) 位的二进制数,表示网络的状态。如果那一位的交换器开启则为 1,否则为 0。

如果有多解,输出字典序最小的解。

每组数据输出之间用空行隔开。

sample input

2

3 2 1 0

3

3 7 4 0 2 6 1 5

0

sample output

00

11

11

0011

0000

0110

1111

1101

@solution@

递归定义的结构可以使用递归求解(要用递归打败递归!)

在 n 阶网络中,不难发现对于第一行的交换器而言,它的左输出端只会连接到左边的 n-1 阶网络,右输出端只会连接到右边的 n-1 阶网络。同理对最后一行的交换器,它的左输入端只会连接到左边的 n-1 阶网络,右输入端只会连接到右边的 n-1 网络。

同时,我们发现如果开启第一行的交换器,只会影响输入端的两个数哪一个进左边的网络,哪一个进右边的网络。最后一行同理。

记 a[i] 表示第一行第 i 个交换器是否打开(打开为 1,否则为 0),b[i] 表示最后一行第 i 个交换器是否打开。

记 c[i] 表示数 i 在第一行哪个交换器输入, d[i] 表示数 i 在最后一行哪个交换器输出。

记 e[i] 表示数 i 在第一行的交换器的左边输入还是右边输入(左边为 0,右边为 1),f[i] 表示数 i 在最后一行的交换器的左边输入还是右边输入。

则如果一个网络合法,对于每一个数 i,一定满足 e[i] xor f[i] xor a[c[i]] xor b[d[i]] = 0。

因为是求字典序最小的解,所以可以在第一行从左到右枚举每一个交换器是 0 还是 1,再通过上面那个式子 bfs 进行合法性判定。

决定好了第一行与最后一行,就可以递归解决两个 n-1 阶的子问题。总时间复杂度 O(2^(2n))。

题目虽然说无解输出 -1,但实际上总是有解,可以通过归纳法证明(虽然我代码还是判了无解的)。

为了实现简单可以总是将第一行的输入端调成 0 1 2 3…… 的形式。

@accepted code@

#include<cstdio>
#include<queue>
using namespace std;
const int MAXN = 13;
int x[1<<MAXN], y[1<<MAXN], tp;
int ans[MAXN<<1][1<<MAXN];
int a[1<<MAXN], n, s, t, u;
int tmp1[1<<MAXN], tmp2[1<<MAXN], tmp3[1<<MAXN], tmp4[1<<MAXN];
int stk3[1<<MAXN], stk4[1<<MAXN], tp3, tp4;
queue<int>que;
void restore() {
while( tp3 ) tmp3[stk3[tp3--]] = -1;
while( tp4 ) tmp4[stk4[tp4--]] = -1;
}
bool check(int x, int y) {
stk3[++tp3] = x, tmp3[x] = y;
que.push(x<<1), que.push(x<<1|1);
while( !que.empty() ) {
int f = que.front(); que.pop();
if( f < (u<<1) ) {
if( tmp4[tmp2[f]>>1] != -1 ) {
if( (tmp3[f>>1] == tmp4[tmp2[f]>>1]) != ((f&1) == (tmp2[f]&1)) ) {
restore();
return false;
}
}
else {
stk4[++tp4] = tmp2[f]>>1;
tmp4[tmp2[f]>>1] = (f&1)^(tmp2[f]&1)^tmp3[f>>1];
que.push((tmp2[f]^1) + (u<<1));
}
}
else {
f -= (u<<1);
if( tmp3[tmp1[f]>>1] != -1 ) {
if( (tmp3[tmp1[f]>>1] == tmp4[f>>1]) != ((f&1) == (tmp1[f]&1)) ) {
restore();
return false;
}
}
else {
stk3[++tp3] = tmp1[f]>>1;
tmp3[tmp1[f]>>1] = (f&1)^(tmp1[f]&1)^tmp4[f>>1];
que.push(tmp1[f]^1);
}
}
}
tp3 = tp4 = 0;
return true;
}
int main() {
freopen("left.in", "r", stdin);
freopen("left.out", "w", stdout);
while( scanf("%d", &n) == 1 && n ) {
s = (1<<n), t = (s>>1);
for(int i=0;i<s;i++)
scanf("%d", &a[i]);
bool flag = true;
for(int i=n;i>=1;i--) {
/*printf("| ");
for(int j=0;j<s;j++)
printf("%d ", a[j]);
puts("");*/
u = (1<<(i-1));
for(int j=0;j<t;j+=u) {
for(int k=0;k<u;k++) {
tmp1[k<<1] = a[(j+k)<<1], tmp1[k<<1|1] = a[(j+k)<<1|1];
tmp2[tmp1[k<<1]] = k<<1, tmp2[tmp1[k<<1|1]] = k<<1|1;
tmp3[k] = tmp4[k] = -1;
}
for(int k=0;k<u;k++) {
if( tmp3[k] == -1 ) {
if( !check(k, 0) && !check(k, 1) ) {
flag = false;
break;
}
}
}
for(int k=0;k<u;k++)
ans[n-i+1][j+k] = tmp3[k], ans[n+i-1][j+k] = tmp4[k];
for(int k=0;k<u;k++) {
if( !tmp4[k] ) a[(j<<1)+k] = (tmp1[k<<1]>>1), a[(j<<1)+k+u] = (tmp1[k<<1|1]>>1);
else a[(j<<1)+k] = (tmp1[k<<1|1]>>1), a[(j<<1)+k+u] = (tmp1[k<<1]>>1);
// printf(". %d %d\n", j+k, j+k+u); /*printf("| ");
for(int j=0;j<s;j++)
printf("%d ", a[j]);
puts("");*/
}
if( !flag ) break;
}
if( !flag ) break;
}
if( !flag ) puts("-1");
else {
for(int i=1;i<=2*n-1;i++) {
for(int j=0;j<t;j++)
printf("%d", ans[i][j]);
puts("");
}
}
puts("");
}
}

@details@

康复计划 - 8。

切水题是真爽~

有一个很烦的细节就是比较器与输入输出端的下标转换。

@NOI模拟2017.06.30 - T1@ Left的更多相关文章

  1. @NOI模拟2017.06.30 - T3@ Right

    目录 @description@ @solution@ @part - 1@ @part - 2@ @accepted code@ @details@ @description@ JOHNKRAM 和 ...

  2. @NOI模拟2017.07.02 - T1@ Attack

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 『新的风暴已经出现,怎么能够停滞不前』--你决定去攻击小怪兽的巢 ...

  3. 7.11 NOI模拟赛 qiqi20021026的T1 四个指针莫队 trie树

    LINK:qiqi20021026的T1 考场上只拿到了50分的\(nq\)暴力. 考虑一个区间和一个区间配对怎么做 二分图最大带权匹配复杂度太高. 先考虑LCS的问题 常见解决方法是后缀数组/tri ...

  4. 5.30 NOI 模拟

    $5.30\ NOI $模拟 高三大哥最后一次模拟考了,祝他们好运 \(T1\)装箱游戏 显然可以将四种字母之间的空缺当做状态枚举 那么这道题就很显然了 #include<bits/stdc++ ...

  5. 5.23 NOI 模拟

    $5.23\ NOI $模拟 \(T1\)简单的计算几何题 \(zjr:\)我当时没改,那么自己看题解吧 倒是有个简单的随机化方法(能获得\(72pts,\)正确性未知)\(:\) 随机两条切椭圆的平 ...

  6. 5.6 NOI模拟

    \(5.6\ NOI\)模拟 明天就母亲节了,给家里打了个电话(\(lj\ hsez\)断我电话的电,在宿舍打不了,只能用教练手机打了) 其实我不是很能看到自己的\(future,\)甚至看不到高三的 ...

  7. 5.4 NOI模拟

    \(5.4\ NOI\)模拟 \(T1\) 想到分讨,但是暴力输出一下方案之后有很多特别的情况要讨论,就弃了... 假设\(a\)是原序列,\(b\)是我们得到的序列 设\(i\)是最长公共前缀,\( ...

  8. hdu6034[模拟] 2017多校1

    /*hdu6034[模拟] 2017多校1*/ //暴力模拟26个26进制数即可, 要注意进位 #include<bits/stdc++.h> using namespace std; t ...

  9. 【NOI】2017 蚯蚓排队(BZOJ 4943,LOJ 2303) 模拟+hash

    [题目]#2303. 「NOI2017」蚯蚓排队 [题意]给定n条长度不超过6的蚯蚓,初始各自在一个队伍.m次操作:1.将i号蚯蚓和j号蚯蚓的队伍合并(保证i为队尾,j为队首).2.将i号蚯蚓和它后面 ...

随机推荐

  1. 【模板】矩阵快速幂 洛谷P2233 [HNOI2002]公交车路线

    P2233 [HNOI2002]公交车路线 题目背景 在长沙城新建的环城公路上一共有8个公交站,分别为A.B.C.D.E.F.G.H.公共汽车只能够在相邻的两个公交站之间运行,因此你从某一个公交站到另 ...

  2. 七牛云+MPic-图床神器搭建

    1. 注册七牛云 2. 新建存储空间 3. 密钥 4. 记录自己账户四个值: 测试域名:xxxxx.xx.clouddn.com ak:xxxxxxxxxxxxxxxxxxxx sk:xxxxxxxx ...

  3. 错觉-Info:视错觉与UI元素间的可能

    ylbtech-错觉-Info:视错觉与UI元素间的可能 1.返回顶部 1. 视觉原理在当下红火的机械视觉中是必不可少的,那在我们日常工作的UI产品设计中又有什么可能性的呢?今天,我从“视错觉”这个角 ...

  4. TextBlock中显示文字和图片,且不会自动换行

    原本TextBlock显示图片是很容易的,即TextBlock.Inlines.Add(UiElement   element):这个方法即可, 但是,会出现如下效果: 我不想要这种效果,所以改了下代 ...

  5. NSURLSessionDownloadTask的深度断点续传

    http://www.cocoachina.com/ios/20160503/16053.html 本文为投稿文章,作者:WeiTChen 对于后台下载与断点续传相信大家肯定不会陌生,那么如果要同时实 ...

  6. 小爬爬5:scrapy介绍2

    1.scrapy:爬虫框架 -框架:集成了很多功能且具有很强通用性的一个项目模板 -如何学习框架:(重点:知道有哪些模块,会用就行) -学习框架的功能模板的具体使用. 功能:(1)异步爬取(自带buf ...

  7. python 同名变量引用

  8. 一条SQL完成跨数据库实例Join查询

    背景 随着业务复杂程度的提高.数据规模的增长,越来越多的公司选择对其在线业务数据库进行垂直或水平拆分,甚至选择不同的数据库类型以满足其业务需求.原本在同一数据库实例里就能实现的SQL查询,现在需要跨多 ...

  9. 【JZOJ4847】【NOIP2016提高A组集训第5场11.2】夕阳

    题目描述 "我有个愿望,我希望在灿烂千阳时遇见你." 这是个有n个点的世界,有m条无向边连接着这n个点,但是不保证点之间能够互相到达. "这个世界的夕阳,只在奇数长的简单 ...

  10. poj1087&&hdu1526 最大流

    多源多汇. 比较明显的建图.对于电器,可以从源点与各个电器相连,容量为1,表示这个电器有1个,然后对于各种接头,那可以各个接头与汇点相连,容量为1,表示每个接头只能用一次. 然后对于能够相互转换的接头 ...