[SDOI2015]排序

Description

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

下面是一个操作事例:
N=3,A[1..8]=[3,6,1,2,7,8,5,4].
第一次操作,执行第3种操作,交换A[1..4]和A[5..8],交换后的A[1..8]为[7,8,5,4,3,6,1,2].
第二次操作,执行第1种操作,交换A[3]和A[5],交换后的A[1..8]为[7,8,3,4,5,6,1,2].
第三次操作,执行第2中操作,交换A[1..2]和A[7..8],交换后的A[1..8]为[1,2,3,4,5,6,7,8].
Input

第一行,一个整数N

第二行,2^N个整数,A[1..2^N]
Output

一个整数表示答案

Sample Input

3

7 8 5 6 1 2 4 3
Sample Output

6

HINT

100%的数据, 1<=N<=12.

Source

Round 1 感谢ZKY制作非官方数据

分析:

显然,对于每一种方案,我改变其操作顺序,仍然不影响结果,所以我们只需枚举每种操作做与不做即可,然后将排列数加入答案即可。

考虑进一步优化,对于第i种操作,将序列分为若干个长为2^(i-1)的小段,由于每种操作只能用一次,则当每个小段各自元素都连续且递增,就不需要这种操作了(相当于每2^(i-1)个为一组,每组都排好了序,要想是整体进一步排序,只能依靠下一步操作来排了),如果有一个不连续递增,则将这组分为两份后交换即可,如果有2组不满足,分四种情况讨论,最后如果超过2个,显然无法使它们有序,则对这种方案剪枝。

关键思想是由局部有序一直操作直至全局有序,当枚举第i种操作时,此时2^(i-2)长度的段必然是有序的(不合法情况已去除),只需考虑2^(i-1)长度的段即可。

program sort;
var
a:array[..]of longint;
n,i,m:longint; ans,tot:int64;
procedure swap(x1,y1,x2,y2:longint);
var i,t:longint;
begin
for i:= to y1-x1 do
begin t:=a[x1+i]; a[x1+i]:=a[x2+i]; a[x2+i]:=t; end;
end;
function cheak:boolean;
var i:longint;
begin
for i:= to m do if a[i]<>a[i-]+ then exit(false);
exit(true);
end;
procedure dfs(x:longint);
var i,j,t,v,s,k:longint; l:int64; w:array[..]of longint;
begin
if x>=n then
begin if cheak=false then exit;l:=;for i:= to tot do l:=l*i; inc(ans,l); exit; end;
t:= shl (x+); v:= shl x; s:=v; k:=;
for i:= to m div t do
begin
if (a[s]+<>a[s+])or(a[s] mod v<>) then begin inc(k); if k> then exit;w[k]:=s; end;
s:=s+t;
end;
if k= then dfs(x+);
inc(tot);
if k= then begin swap(w[]-v+,w[],w[]+,w[]+v); dfs(x+); swap(w[]-v+,w[],w[]+,w[]+v); end;
if k= then
begin
if (a[w[]]+=a[w[]+])and(a[w[]]+=a[w[]+]) then
begin
swap(w[]-v+,w[],w[]-v+,w[]); dfs(x+); swap(w[]-v+,w[],w[]-v+,w[]);
swap(w[]+,w[]+v,w[]+,w[]+v); dfs(x+); swap(w[]+,w[]+v,w[]+,w[]+v);
end;
if (a[w[]]+=a[w[]-v+])and(a[w[]+v]+=a[w[]+]) then
begin swap(w[]-v+,w[],w[]+,w[]+v);dfs(x+); swap(w[]-v+,w[],w[]+,w[]+v);end;
if (a[w[]+v]+=a[w[]+])and(a[w[]]+=a[w[]-v+]) then
begin swap(w[]+,w[]+v,w[]-v+,w[]);dfs(x+); swap(w[]+,w[]+v,w[]-v+,w[]); end;
end;
dec(tot);
end;
begin
readln(n);m:= shl n;
for i:= to m do read(a[i]);
ans:=; tot:=;
dfs();
writeln(ans);
end.

BZOJ 3990: [SDOI2015]排序(搜索+剪枝)的更多相关文章

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

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

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

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

  3. BZOJ.3990.[SDOI2015]排序(DFS)

    题目链接 操作序列的顺序显然是无关的,所以只需按特定顺序求出一个长度为\(l\)的操作序列,它对答案的贡献为\(l!\). 我们从小到大枚举所有选择.若当前为第\(i\)个,如果有一段长度为\(2^i ...

  4. BZOJ 3990 [SDOI2015]排序

    题解: 首先很容易看出各个操作是互不影响的,即对于一个合法的操作序列,我们可以任意交换两个操作的位置而不影响合法性. 因此我们可以忽略操作先后的影响,只考虑这个操作是否会出现在操作序列中. 如果用2n ...

  5. [bzoj3990][SDOI2015]排序-搜索

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

  6. 【搜索】BZOJ 3990: 【Sdoi 2015】排序

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

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

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

  8. hdu 5887 搜索+剪枝

    Herbs Gathering Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  9. 搜索+剪枝——POJ 1011 Sticks

    搜索+剪枝--POJ 1011 Sticks 博客分类: 算法 非常经典的搜索题目,第一次做还是暑假集训的时候,前天又把它翻了出来 本来是想找点手感的,不想在原先思路的基础上,竟把它做出来了而且还是0 ...

随机推荐

  1. hdu1863 畅通工程---MST&连通

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1863 题目大意: 中文题,求MST权值,如果不连通,输出? 解题思路: 这道题帮我找出了之前模板中的 ...

  2. 移动端调试利器-vConsole

    现在移动端开发越来越火,随之而来的问题也越来越多,今天给大家介绍一款移动端调试神器,vconsole. 一.先引用文件,可以从https://www.bootcdn.cn/vConsole/下载,也可 ...

  3. centos 6 安装VMware Tools

    开启虚拟机的centos系统, 在虚拟机工具栏点击 “虚拟机”=>VMwareTools安装,  centos系统内的桌面会有一个VMware Tools的驱动光驱, 双击打开后,有一个tar. ...

  4. runtime消息转发机制

    Objective-C 扩展了 C 语言,并加入了面向对象特性和 Smalltalk 式的消息传递机制.而这个扩展的核心是一个用 C 和 编译语言 写的 Runtime 库.它是 Objective- ...

  5. js display, visible 区别

    注意: display:none和visible:hidden都能把网页上某个元素隐藏起来,在视觉效果上没有区别,但是在一些DOM操作中两者有区别: display:none ---不为被隐藏的对象保 ...

  6. ZRDay6A. 萌新拆塔(三进制状压dp)

    题意 Sol 这好像是我第一次接触三进制状压 首先,每次打完怪之后吃宝石不一定是最优的,因为有模仿怪的存在,可能你吃完宝石和他打就GG了.. 因此我们需要维护的状态有三个 0:没打 1:打了怪物 没吃 ...

  7. 5.7 并行复制配置 基于GTID 搭建中从 基于GTID的备份与恢复,同步中断处理

    5.7 并行复制配置 基于GTID 搭建中从 基于GTID的备份与恢复,同步中断处理 这个文章包含三个部分 1:gtid的多线程复制2:同步中断处理3:GTID的备份与恢复 下面文字相关的东西 大部分 ...

  8. Zabbix监控oracle各服务器连接数

    需求: 根据机器名查询oracle连接数,并通过zabbix进行监控 脚本: [root@rac1 Zabbix_S]# cat get_conns.py#!/usr/bin/python#codin ...

  9. Linux下重要日志及查看方式

    1.Linux下重要日志文件介绍 /var/log/boot.log 该文件记录了系统在引导过程中发生的事件,就是Linux系统开机自检过程显示的信息,如图1所示: 图1 /var/log/boot. ...

  10. ThinkPHP邮件发送S(Smtp + Mail + phpmailer)

    三种邮件发送介绍:(Smtp,Mail以及phpmailer)ThinkPhp 框架下开发. 邮件发送配置先前准备(用该账号做测试用):(这里用新浪邮箱服务器)将自己的新浪邮箱开通 POP3/SMTP ...