Brief Description

小A有一个1-2N的排列A[1..2N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1<=i<=N),第i中操作为将序列从左到右划分为2{N-i+1}段,每段恰好包括2{i-1}个数,然后整体交换其中两段.小A想知道可以将数组A从小到大排序的不同的操作序列有多少个,小A认为两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同).

Algorithm Design

首先不难发现操作顺序不影响答案, 我们只需要考察每种操作是否选中, 若选中交换哪两块就好了. 一个合法的操作序列如果有\(n\)个操作, 那么可以给答案\(contribute\ n!\). 我们从小到大考察每一种操作, 首先, 可以知道, 对于操作\(2^i\), 序列肯定已经被分成了\(2^{n-i+1}\)个有序数列, 我们首先检查是否有序, 如果有问题直接\(return\). 然后扫描每个块, 每两个块都必须是有序的, 否则要交换. 如果\(tot \geqslant 4\)那么一定不合法. 代码表达的非常清楚.

Code

#include <algorithm>
#include <cstdio>
#define ll long long
const int maxn = 1 << 13;
int n;
int a[maxn];
ll po[13];
ll ans;
bool check(int k) {
for (int i = 1; i <= (1 << (n - k)); i++)
if (a[(i - 1) * (1 << k) + 1] + (1 << (k - 1)) !=
a[(i - 1) * (1 << k) + (1 << (k - 1)) + 1])
return 0;
return 1;
}
void swap(int i, int j, int k) {
for (int m = 1; m <= k; m++)
std::swap(a[i + m - 1], a[j + m - 1]);
}
void dfs(int now, int num) {
if (now && !check(now))
return;
if (now == n) {
ans += po[num];
return;
}
dfs(now + 1, num);
int tmp[5], tot = 0;
for (int i = 1; i <= (1 << (n - now)); i += 2)
if (a[i * (1 << now) + 1] != a[(i - 1) * (1 << now) + 1] + (1 << now)) {
if (tot == 4)
return;
tmp[++tot] = i;
tmp[++tot] = i + 1;
}
if (!tot)
return;
for (int i = 1; i <= tot; i++)
for (int j = i + 1; j <= tot; j++) {
swap((1 << now) * (tmp[i] - 1) + 1, (1 << now) * (tmp[j] - 1) + 1,
1 << now);
dfs(now + 1, num + 1);
swap((1 << now) * (tmp[i] - 1) + 1, (1 << now) * (tmp[j] - 1) + 1,
1 << now);
}
}
int main() {
// freopen("input", "r", stdin);
po[0] = 1;
for (int i = 1; i <= 12; i++)
po[i] = po[i - 1] * i;
scanf("%d", &n);
for (int i = 1; i <= 1 << n; i++)
scanf("%d", &a[i]);
dfs(0, 0);
printf("%lld", ans);
}

[bzoj3990][SDOI2015]排序-搜索的更多相关文章

  1. BZOJ 3990: [SDOI2015]排序 [搜索]

    3990: [SDOI2015]排序 题意:\(2^n\)的一个排列,给你n种操作,第i种把每\(2^{i-1}\)个数看成一段,交换任意两段.问是这个序列有序的操作方案数,两个操作序列不同,当且仅当 ...

  2. [BZOJ3990][SDOI2015]排序(DFS)

    3990: [SDOI2015]排序 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 902  Solved: 463[Submit][Status][ ...

  3. [BZOJ3990]:[SDOI2015]排序(搜索)

    题目传送门 题目描述 小A有一个1-${2}^{N}$的排列A[1..${2}^{N}$],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1≤i≤N), ...

  4. BZOJ3990 [SDOI2015]排序 【搜索】

    题目 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1<=i<=N),第i中操作为将序列从左到 ...

  5. Bzoj3990 [SDOI2015]排序

    Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 651  Solved: 338 Description 小A有一个1-2^N的排列A[1..2^N], ...

  6. BZOJ 3990 [SDOI2015]排序 ——搜索

    [题目分析] 可以发现,操作的先后顺序是不影响结果的,那么答案就是n!的和. 可以从小的步骤开始搜索,使得每一个当前最小的块都是上升的数列,然后看看是否可行即可. 复杂度好像是4^n [代码](哪里写 ...

  7. BZOJ 3990: [SDOI2015]排序(搜索+剪枝)

    [SDOI2015]排序 Description 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作有N种,每种操作最多可以执行一次,对于所有的i(1< ...

  8. 006-筛选分类排序搜索查找Filter-Classificatio-Sort-Search-Find-Seek-Locate

    006-筛选分类排序搜索查找Filter-Classificatio-Sort-Search-Find-Seek-Locate https://www.cnblogs.com/delphixx/p/1 ...

  9. 【LG3322】[SDOI2015]排序

    [LG3322][SDOI2015]排序 题面 洛谷 题解 交换顺序显然不影响答案,所以每种本质不同的方案就给答案贡献次数的阶乘. 从小往大的交换每次至多\(4\)中决策,复杂度\(O(4^n)\). ...

随机推荐

  1. 【leetcode】19. 删除链表的倒数第N个节点

    描述 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例 给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后,链表变 ...

  2. kubernetes(k8s) 集群

    开启和重启命令: sudo systemctl stop etcdsudo systemctl stop dockersudo systemctl stop kube-apiserversudo sy ...

  3. websocket协议详解;

    websocket是基于http协议,借用http协议来完成连接阶段的握手: 当连接建立后,浏览器和服务器之间的通信就和http协议没有关系了,b.s之间只用websocket协议来完成基本通信. = ...

  4. 揭开网络编程常见API的面纱【上】

    Linux网络编程API函数初步剖析 今天我们来分析一下前几篇博文中提到的网络编程中几个核心的API,探究一下当我们调用每个API时,内核中具体做了哪些准备和初始化工作. 1.socket(famil ...

  5. poi excel导出 xssf 带下拉框

    需求:导出之后带有二级级联的下拉框.(类似于省市). 最初的思路是怀疑是不是数组内串太多了,导出之后的excel有36行,调试的误区在于刚开始认为对行数有限制,后自己写了一个测试类,才发现不是行数,而 ...

  6. [剑指Offer] 23.二叉搜索树的后序遍历

    [思路]BST的后序序列的合法序列是,对于一个序列S,最后一个元素是x (也就是根),如果去掉最后一个元素的序列为T,那么T满足:T可以分成两段,前一段(左子树)小于x,后一段(右子树)大于x,且这两 ...

  7. Python 类和对象-上

    #类和对象 class Human: #属性 -> 成员属性(变量) ear = 2 mouth = 1 sex = 'man' age = 28 name = 'zhangwang' marr ...

  8. BZOJ4105 THUSC2015平方运算(线段树)

    注意到模数被给出且非常小,做法肯定要依赖于一些与此相关的性质.找题解打表可以发现循环节长度的lcm不超过60. 考虑怎么用线段树维护循环.对线段树上每个点维护这段区间的循环节.在循环中的位置,如果未进 ...

  9. SRM708 div1 PalindromicSubseq(动态规划+容斥原理)

    题目大意:给定一个字符串,记X[i]为包含s[i]这个字符的所有子列是回文串的个数(注意是子列而不是子串),求出所有的X[i]*(i+1),然后异或起来作为返回结果 题解: 首先用容斥来想,如果当前枚 ...

  10. [bzoj2901]矩阵求和

    题目大意:给出两个$n\times n$的矩阵,$m$次询问它们的积中给定子矩阵的数值和. 题解:令为$P\times Q=R$ $$\begin{align*}&\sum\limits_{i ...