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

正解居然是搜索,考场上看这板儿B是个神仙状压就skip掉了

后悔啊……把猛肝某APIO2016T1的时间放这题上怎么还没30分啊……

手%几组数据可以发现,操作序列的合法性与顺序无瓜

所以只需确定序列中有没有第i种操作,最后将统计结果的阶乘输出即为序列数

枚举操作种数i,+1什么的太麻烦就直接分成$2^{N-i}$段,每段$2^i$个数

然后要交换的话就需要找非严格递增序列($a_{x+1}!=a_x+1$)

超过两个显然不可行,直接return

接下来分类讨论:

如果没有这样的序列,继续dfs

如果有一个,尝试内部一分为二后交换使之满足严格递增

如果有两个,两段分成四段尝试交换

(感谢hzwer的题解 大大减少了我的代码量 两层for分类讨论确实比四个if else美观多辽)

收获:看到二进制不要直接想状压,还有可能是树形结构或者二分搜索

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=(<<)+;
int n,a[N],tot;
long long ans=,bin[],fac[];
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void ini()
{
bin[]=fac[]=;
for(int i=;i<=;i++)
bin[i]=bin[i-]<<,fac[i]=1LL*i*fac[i-];
}
bool judge(int p,int k)
{
for(int j=;j<bin[k];j++)
if(a[p+j]!=a[p+j-]+)return ;
return ;
}
void sw_(int x,int y,int k)
{
for(int i=;i<bin[k];i++)
swap(a[x+i],a[y+i]);
}
void dfs(int p,int val)
{
if(p==n+)
{
ans+=fac[val];
return ;
}
int bl1,bl2;bl1=bl2=;
for(int i=;i<=bin[n];i+=bin[p])
if(!judge(i,p))
{
if(!bl1)bl1=i;
else if(!bl2)bl2=i;
else return ;
}
if(!bl1&&!bl2)dfs(p+,val);
else if(bl1&&!bl2)
{
sw_(bl1,bl1+bin[p-],p-);
dfs(p+,val+);
sw_(bl1,bl1+bin[p-],p-);
}
else
{
for(int num1=;num1<;num1++)
for(int num2=;num2<;num2++)
{
sw_(bl1+num1*bin[p-],bl2+num2*bin[p-],p-);
if(judge(bl1,p)&&judge(bl2,p))
{
dfs(p+,val+);
sw_(bl1+num1*bin[p-],bl2+num2*bin[p-],p-);
break;
}
sw_(bl1+num1*bin[p-],bl2+num2*bin[p-],p-);
}
}
}
int main()
{
n=read();
ini();
for(int i=;i<=bin[n];i++)
a[i]=read();
dfs(,);
cout<<ans<<endl;
return ;
}

[SDOI2015]排序 题解 (搜索)的更多相关文章

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

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

  2. [sdoi2015]排序(搜索+剪枝优化)

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

  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]排序——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3990 小A有一个1-2^N的排列A[1..2^N],他希望将A数组从小到大排序,小A可以执行的操作 ...

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

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

  7. 【LG3322】[SDOI2015]排序

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

  8. MVC5 + EF6 + Bootstrap3 (11) 排序、搜索、分页

    系列教程:MVC5 + EF6 + Bootstrap3 上一节:MVC5 + EF6 + Bootstrap3 (10) 数据查询页面 源码下载:点我下载 我工作的源码:http://www.jin ...

  9. numpy教程:排序、搜索和计数

    http://blog.csdn.net/pipisorry/article/details/51822775 numpy排序.搜索和计数函数和方法.(重新整合过的) ],, , ], [, , ]] ...

随机推荐

  1. 07-图5 Saving James Bond - Hard Version(30 分)

    This time let us consider the situation in the movie "Live and Let Die" in which James Bon ...

  2. ZROI week5

    考试 Part 简单题,从结尾倒着扫一遍就行. Pref 选一个最长的好的序列. 题目有点小简单,似乎直接哈希就行,然后还打了一遍\(kmp\). Chess 一道很不错的题目,用异或维护修改即可. ...

  3. (转)Spring Boot干货系列:(三)启动原理解析

    转:http://tengj.top/2017/03/09/springboot3/ 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂Spri ...

  4. ArcGIS Runtime SDK for .NET (Quartz Beta)之连接ArcGIS Portal

    1. 介绍 ArcGIS Portal作为ArcGIS平台的中枢,在ArcGIS体系中起着至关重要的地位.在ArcGIS Runtime的新架构Quartz中添加了连接ArcGIS Portal(或A ...

  5. C++笔试题之宏定义相关

    1. #define CALC(X) X*X int i; i=CALC(+)/(+); cout<<i<<endl; 输出:31 宏定义在替换处展开为:i = 5+5*5+5 ...

  6. javaScript 通过location对象获取项目的url

    项目中有些要通过jQuery 动态加载,其中需要一些路径,使用相对路径会出现错误,报 $("#t1").html("设置或返回从井号 (#) 开始的 URL(锚)---& ...

  7. Rust <0>:源代码组织,Cargo 入门

    Rust 源代码组织,使用配套的 Cargo 工具,其功能强大,程序员可摆脱 C/C++ 中需要自行维护 make.cmake 之类配置的工作量. 初始化一个项目: cargo new --bin h ...

  8. python基础【第五篇】

    python第三节 1.整型及布尔值 1.1 进制转换 十进制 ----二进制 二进制 ----十进制 8421方法与普通计算 python中十进制转二进制示例:bin(51)>>> ...

  9. python 包管理工具 pip 的配置

    近几年来,python的包管理系统pip 越来越完善, 尤其是对于 windows场景下,pip大大改善了python的易用性. https://www.cnblogs.com/yvivid/p/pi ...

  10. js保留两位小数的方法

    js保留两位小数的方法如下 1.toFixed()方法 需注意,保留两位小数,将数值类型的数据改变成了字符串类型 2.Math.floor(),不四舍五入 ,向下取整 注意,不改变数据类型 3.字符串 ...