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. 【Linux】 Centos7 安装 mysql-8.0

    本文介绍使用rpm包安装mysql, 以 mysql-8.0.17-1.el7.x86_64.rpm-bundle.tar 为例: 1.下载 MySQL下载地址:https://dev.mysql.c ...

  2. Random Point in Triangle

    题目链接 题意:多组输入三角形各个顶点坐标p1,p2,p3,在三角形中任取一点p,计算 期望E=max(S(p,p1,p2),max(S(p,p1,p3),S(p,p2,p3))); 思路:用随机数找 ...

  3. [CSP-S模拟测试51]题解

    错失人生中第一次AK的机会…… A.attack 支配树板子题.考场上发明成功√ 首先支配树上两点路径之间的点都是必经之点,根据这个性质我们就可以yy出建树的方法.跑拓扑,在每个点(设为$x$)即将入 ...

  4. [CSP-S模拟测试48]反思+题解

    状态很垃圾的一场考试.感觉“这么多分就够了”的心态很是在给自己拖后腿. 打开题面,第一页赫然写着:$Claris' Contest$. 吓得我差点手一抖关掉.不过后来想想似乎强到变态的人出的题都不是很 ...

  5. STM32例程之USB HID双向数据传输(源码下载)【转】

    程序功能 将STM32的USB枚举为HID设备. STM32使用3个端点,端点0用于枚举用,端点1和2用于数据的发送和接收. 端点长度为64,也就是单次最多可以传输64个字节数据. STM32获取上位 ...

  6. springboot bootstrap.yml 和 application.yml

    bootstrap.yml可以理解成系统级别的一些参数配置,这些参数一般是不会变动的 application.yml 可以用来定义应用级别的,如果搭配spring-cloud-config使用 app ...

  7. Eclipse转idea改设置

    1 自动导包:画圈的打钩,实现自动导包,去除无用包.导入的类名相同时需要自己手动导包->  alt+enter. 2:修改快捷键 左移光标,右移同理. 上移光标:下移同理 光标移至行首,行末为e ...

  8. angular-file-upload插件的使用简单介绍

    参考博客: https://www.cnblogs.com/jarson-7426/p/5191156.html angular-file-upload 最近一段时间用了一下angular-file- ...

  9. XStream教程

    XStream是一个简单的基于Java库,Java对象序列化到XML,反之亦然(即:可以轻易的将Java对象和xml文档相互转换). 特点 使用方便 - XStream的API提供了一个高层次外观,以 ...

  10. _cdecl 与 _stdcall 区别

    前段时间编程时遇到过这么一个问题,我写了一个DLL,把里面的一个函数导出来,然后再定义一个签名与其匹配的函数指针,动态地把这个DLL加载起来(LoadLibrary),得到函数指针后,一调用,结果报错 ...