问题描述

小A有一个1-2N的排列A[1..2N],他希望将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].

输入格式

第一行,一个整数N第二行,2N个整数,A[1..2N]。

输出格式

一个整数表示答案

样例输入

3

7 8 5 6 1 2 4 3

样例输出

6

数据范围

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

解析

首先可以想到的是每次排序交换的两个块中一定是有序的,那么我们从小到大讨论每一种操作,如果对于第\(i\)种操作,序列每个长度为\(2^{i-1}\)的块都是有序的,那么就看长度为\(2^i\)的块有哪些不是单调递增的。如果不满足要求的块的数量大于2,就无解。否则若数量为1,就交换那一块的两半;数量为2就分4部分两两交换。至于有序的判断,可以用排列的性质,如果块最右边的值减去最左边的值等于块长,说明有序。

另外,对于一个操作序列,任意交换两个元素是没有影响的,所以每找到一个长为\(n\)的操作序列,都要增加\(n!\)中方案。

代码

#include <iostream>
#include <cstdio>
#define N 5000
using namespace std;
int n=1,m,i,a[N];
long long ans,f[N];
int read()
{
char c=getchar();
int w=0;
while(c<'0'||c>'9') c=getchar();
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w;
}
void dfs(int x,int sum)
{
int gap=(1<<(x-1)),gap1=gap<<1;
for(int i=1;i<=n&&x>1;i+=gap){
if(a[i+gap-1]-a[i]!=gap-1) return;
}
if(x==m+1){
ans+=f[sum];
return;
}
dfs(x+1,sum);
int op[5],cnt=0;
for(int i=1;i<=n;i+=gap1){
int j=(2*i+gap1-1)/2+1;
if(a[i+gap1-1]-a[i]!=gap1-1){
op[++cnt]=i;
op[++cnt]=j;
}
}
if(cnt>4) return;
for(int i=1;i<=cnt;i++){
for(int j=i+1;j<=cnt;j++){
for(int k=0;k<gap;k++) swap(a[op[i]+k],a[op[j]+k]);
dfs(x+1,sum+1);
for(int k=0;k<gap;k++) swap(a[op[i]+k],a[op[j]+k]);
}
}
}
int main()
{
m=read();
for(i=1;i<=m;i++) n*=2;
f[0]=1;
for(i=1;i<=12;i++) f[i]=f[i-1]*i;
for(i=1;i<=n;i++) a[i]=read();
dfs(1,0);
printf("%lld\n",ans);
return 0;
}

[洛谷P3322] SDOI2015 排序的更多相关文章

  1. 洛谷P3324 [SDOI2015]星际战争

    题目:洛谷P3324 [SDOI2015]星际战争 思路: 类似<导弹防御塔>,因为题目保证有解,花费时间小于最终答案时一定无法消灭所有敌人,只要花费时间大于等于最终答案都可以消灭所有敌人 ...

  2. [洛谷P2127] 序列排序

    洛谷题目链接:序列排序 题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? ...

  3. 题解 P3322 [SDOI2015]排序

    题解 仔细审题,我们会发现 小 \(A\) 认为两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同). 所以,对于一种操作,不管是交换哪两段,都算作同一种操作,只会 ...

  4. LOJ #2185 / 洛谷 P3329 - [SDOI2015]约数个数和(莫比乌斯函数)

    LOJ 题面传送门 / 洛谷题面传送门 题意: 求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)\),\(d(x)\) 为 \(x\) 的约数个数. \( ...

  5. 【洛谷P1347】排序

    题目大意:给定 N 个变量和 M 个变量之间的偏序关系,问能否求出这 N 个变量之间的一个全序.若能,输出最少利用多少条已知信息即可求的结果,且输出该全序:若无解,输出到第几条已知信息可以判定无解:若 ...

  6. 洛谷P3809 后缀排序【后缀数组】【模板】

    题目背景 这是一道模板题. 题目描述 读入一个长度为 nn 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置.位置编 ...

  7. 洛谷P2127 序列排序 [贪心]

    题目传送门 题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? 输入输出格 ...

  8. [UVA1402]Robotic Sort;[SP2059]CERC07S - Robotic Sort([洛谷P3165][CQOI2014]排序机械臂;[洛谷P4402][Cerc2007]robotic sort 机械排序)

    题目大意:一串数字,使用如下方式排序: 先找到最小的数的位置$P_1$,将区间$[1,P_1]$反转,再找到第二小的数的位置$P_2$,将区间$[2,P_2]$反转,知道排序完成.输出每次操作的$P_ ...

  9. 洛谷——P1327 数列排序

    P1327 数列排序 题目描述 给定一个数列{an},这个数列满足ai≠aj(i≠j),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换? 输入输出格式 输入格式: ...

随机推荐

  1. Linux进程: task_struct结构体成员

    一:简介 为了管理进程,内核必须对每个进程所做的事情进行清除的描叙. 比如:内核必须知道进程优先级,他是正在CPU上运行还是因为某些事件被阻塞了,给它分配了什么样的地址空间,允许它访问哪个文件等等.这 ...

  2. 【VS开发】VS2013多字节工程问题uilding an MFC project for a non-Unicode character set is deprecated

    VS2013多字节工程问题 使用VS2013编译旧版VC++程序时,提示Building an MFC project for a non-Unicode character set is depre ...

  3. 【VS开发】【智能语音处理】DTW算法(语音识别)

    DTW主要是应用在孤立词识别的算法,用来识别一些特定的指令比较好用,这个算法是基于DP(动态规划)的算法基础上发展而来的.这里介绍语音识别就先介绍下语音识别的框架,首先我们要有一个比对的模版声音,然后 ...

  4. JS 截取字符的方法

    substr() 方法 substr() 方法可在字符串中抽取从 start 下标开始的指定数目的字符. stringObject.substr(start,length) start:必需.要抽取的 ...

  5. JSR303 校验扩展(分组、按顺序校验)

    1.在spring MVC 项目中使用JSR303 校验数据合法性,一般情况下使用方法为 (1)在接受数据的实体使用注解标添加校验规则 package com.hzsj.wechatdto; impo ...

  6. POJ - 1251 Jungle Roads (最小生成树&并查集

    #include<iostream> #include<algorithm> using namespace std; ,tot=; const int N = 1e5; ]; ...

  7. [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表)

    [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表) 题面 Byteasar 想在墙上涂一段很长的字符,他为了做这件事从字符的前面一段中截取了一段 ...

  8. js知识点——1

    onload 事件会在页面或图像加载完成后立即发生. document.write("内容")将在加载页面时输出 内容可以是什么,可以是一个标签,它输出的文件不能自动换行: < ...

  9. YOLOv3训练过程笔记

    本人使用的是linux平台,按照YOLO网页0https://pjreddie.com/darknet/yolo/的步骤操作进行下载darkenet程序包以及编译,之后可尝试用VOC2007的数据集测 ...

  10. 手把手 教你把H5页面打造成windows 客户端exe 软件

    序言: 好久没有更新博客了,最近在工作中碰到这种需求,由于没有做过,中间碰到好多坑,最后在一位贵人帮助的情况下,最终还是搞定了. 第一步,先安装 cefpython3 pip install cefp ...