A. 排序

题目描述

输入格式

输出格式

一行,一个整数,表示可以将数组A从小到大排序的不同的操作序列的个数。

样例

样例输入

3
7 8 5 6 1 2 4 3

样例输出

6

数据范围与提示

对于30%的数据,1<=N<=4; 对于全部的数据,1<=N<=12。

一个伪装成计数题的大搜索…

首先要知道一个结论:对于一个操作序列,如果他是合法的,那么他的全排列都是合法的,所以从小到大搜索,同时记录操作数k。

对于第x次操作,把序列分成2x-1段,暴力搜索有几段不满足a[i]=a[i-1]+1(注意这里并不只是要求满足递增),如果大于两段,显然无解;

如果没有,则第x操作无需进行(即对答案无贡献),直接向下递归即可,因为如果此时进行第x次操作,会将顺序打乱,之后的操作并不能使之还原。

如果有1段,则将这一段从中间断开,暴力交换,如果仍不满足则无解,满足则继续向下递归,k++;

如果有2端,则有四种情况,暴力交换向下递归即可,注意回溯时要还原。

结束条件:a[i]=i,答案为k!(即A(k,k));

不过这题看起来复杂度好高啊,居然能跑的这么快…

#include<iostream>
#include<cstdio>
#include<cmath>
#define LL long long
using namespace std;
int n,m=1;
int a[5010];
LL jc[15]; bool end()
{
for(int i=1;i<=m;i++)if(a[i]!=i)return 0;return 1;
}
void swapp(int l1,int r1,int l2,int r2)
{
for(int i=l1,j=0;i<=r1;i++,j++)
swap(a[i],a[l2+j]);
}
LL dfs(int x,int k)
{
if(end())return jc[k];
int len=pow(2,x),num=pow(2,n-x),te=0;
int pd=0,d1=0,d2=0;
for(int i=1;i<=num;i++)
for(int j=(i-1)*len+2;j<=i*len;j++)
if(a[j]!=a[j-1]+1) pd++,d1?d2=i:d1=i;
if(pd>2)return 0;
if(!pd)return dfs(x+1,k);
if(pd==1)
{
int l=(d1-1)*len+1,r=(d1)*len;bool pp=0;LL res=0;
swapp(l,(l+r)>>1,(l+r)/2+1,r);
for(int i=l+1;i<=r;i++)
if(a[i]<a[i-1]){pp=1;break;}
if(!pp)res=dfs(x+1,k+1);
swapp(l,(l+r)>>1,(l+r)/2+1,r);
return res;
}
if(pd==2)
{
int l1=(d1-1)*len+1,r1=(d1)*len,l2=(d2-1)*len+1,r2=(d2)*len;
int mid1=(l1+r1)>>1,mid2=(l2+r2)>>1;
LL res=0;
swapp(l1,mid1,l2,mid2);
{
int pp=0;
for(int i=l1+1;i<=r1;i++)
if(a[i]<a[i-1]){pp=1;break;}
for(int i=l2+1;i<=r2;i++)
if(a[i]<a[i-1]||pp){pp=1;break;}
if(!pp) res+=dfs(x+1,k+1);
}
swapp(l1,mid1,l2,mid2);
swapp(l1,mid1,mid2+1,r2);
{
int pp=0;
for(int i=l1+1;i<=r1;i++)
if(a[i]<a[i-1]){pp=1;break;}
for(int i=l2+1;i<=r2;i++)
if(a[i]<a[i-1]||pp){pp=1;break;}
if(!pp) res+=dfs(x+1,k+1);
}
swapp(l1,mid1,mid2+1,r2);
swapp(mid1+1,r1,l2,mid2);
{
int pp=0;
for(int i=l1+1;i<=r1;i++)
if(a[i]<a[i-1]){pp=1;break;}
for(int i=l2+1;i<=r2;i++)
if(a[i]<a[i-1]||pp){pp=1;break;}
if(!pp) res+=dfs(x+1,k+1);
}
swapp(mid1+1,r1,l2,mid2);
swapp(mid1+1,r1,mid2+1,r2);
{
int pp=0;
for(int i=l1+1;i<=r1;i++)
if(a[i]<a[i-1]){pp=1;break;}
for(int i=l2+1;i<=r2;i++)
if(a[i]<a[i-1]||pp){pp=1;break;}
if(!pp) res+=dfs(x+1,k+1);
}
swapp(mid1+1,r1,mid2+1,r2);
return res;
}
}
inline int read()
{
int s=0;char a=getchar();
while(a<'0'||a>'9')a=getchar();
while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
return s;
}
signed main()
{
// freopen("in.txt","r",stdin); n=read();for(int i=1;i<=n;i++)m*=2;
for(int i=1;i<=m;i++)a[i]=read();
jc[0]=1;for(int i=1;i<=12;i++)jc[i]=jc[i-1]*i;
printf("%lld\n",dfs(0,0));
}

【SDOI2015】bzoj3990 排序的更多相关文章

  1. [SDOI2015][bzoj3990] 序列 [搜索]

    题面 传送门 思路 首先,这道题目有一个非常显然(但是我不会严格证明,只能意会一下)的结论:一个合法的操作序列中,任意两个操作是可以互换的 那么,这个结论加上本题极小的数据范围,为什么不搜索一下呢? ...

  2. BZOJ3990 排序(sort)

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

  3. 【LOJ】#2181. 「SDOI2015」排序

    题解 还以为是啥毒瘤题 然后是个搜索题 复杂度算起来挺大 然后跑起来就连0.1ms不到= = 就是从大到小进行每种操作,搜出来一种操作就乘上一个操作数的阶乘就行 如果现在进行的操作操作\(2^i\)那 ...

  4. BZOJ3990 排序

    题目:www.lydsy.com/JudgeOnline/problem.php?id=3990 这题很不错. 刚开始时无从下手,想了好多$O((2^n)log(2^n))$ 的idea,但是都不行. ...

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

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

  6. Bzoj3990 [SDOI2015]排序

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

  7. BZOJ3990:[SDOI2015]排序——题解

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

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

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

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

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

随机推荐

  1. 面试Nginx的几个常见问题(

    1.Nginx 服务器上的 Master 和 Worker 进程分别是什么 Master 进程:读取及评估配置和维持 Worker 进程:处理请求   2.怎么添加模块? Firstly, you h ...

  2. 使用Python进行文件操作

    作为高级语言,对文件进行操作时必不可少的功能.那么,Python是怎么对文件进行操作的呢? 1.什么是文件? 文件是一个存储在辅助存储器上的数据序列,可以包含任何数据内容. 文件包括两种类型:文本文件 ...

  3. 访问者模式(Visitor、Element、accept、ObjectStructure、)(操作外置,与数据结构分离)

    访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作.从定义可以看出结构对象是使用访问者模式的必备条件,而且这个结构对象必须存在遍历自身各个 ...

  4. python基础--包、logging、hashlib、openpyxl、深浅拷贝

    包:它是一系列模块文件的结合体,表现形式就是一个文件夹,该文件夹内部通常会有一个__init__.py文件,包的本质还是一个模块. 首次导入包:(在导入语句中中 . 号的左边肯定是一个包(文件夹)) ...

  5. oracle常用的时间格式转换

    1:取得当前日期是本月的第几周  select to_char(sysdate,'YYYYMMDD W HH24:MI:SS') from dual; TO_CHAR(SYSDATE,'YY') se ...

  6. UE4物理模块(三)---碰撞查询(下)SAP/MBP/BVH算法简介

    在上一文中介绍了碰撞查询的配置方法: Jerry:UE4物理模块(三)---碰撞查询(上)​zhuanlan.zhihu.com 本篇介绍下UE4的各种零大小的射线检测,以及非零大小(带体积)的射线检 ...

  7. PHP获取真实客户端的真实IP的方法

    REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP.如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP. HTTP_CLIENT_IP 是代理服务器发送的HTTP头. ...

  8. 【风马一族_win10设置热点】win10无法开启热点怎么办

    输入cmd,设置管理员开启 输入netsh wlan set hostednetwork mode=allow ssid=name(无线名字) key=00000000(8位以上密码); 输入nets ...

  9. golang标准库中有些函数只有签名没有函数体是怎么回事?

  10. poj 2001 Shortest Prefixes(字典树trie 动态分配内存)

    Shortest Prefixes Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 15610   Accepted: 673 ...