题解

仔细审题,我们会发现

小 \(A\) 认为两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同)。

所以,对于一种操作,不管是交换哪两段,都算作同一种操作,只会对答案贡献一次。

引理

对于一个合法的操作序列,其中的操作可以互换位置,仍为合法序列。

可以自己手动模拟一下,结论很显然。

那么对于每一次操作,设此次操作的长度为 \(len=2^x\),我们将从头开始每 \(len\) 的长度分为一个块,则有 \(2^{n-x}\) 个块。

对于每一个块,我们要保证他是一个合法的有序序列,又因为 \(2^x\) 是由 \(2^{x-1}\) 的块调整顺序转移而来的,那么对于每个 \(2^{x-1}\) 的块,我们就要找出有多少个两两的块不符合顺序递增。如果有超过两对不合理,则我们可以直接判定此分支下无解,

原因就是对于每种操作,我们只能用一次。

当到边界时且合法时,我们需要加上用到的操作数的阶乘。(原因见引理)

\(AC \kern 0.5emCODE:\)

#include<bits/stdc++.h>
#define ri register int
#define p(i) ++i
using namespace std;
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
inline char gc() {return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline int read() {
ri x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
return x*f;
}
}
using IO::read;
namespace nanfeng{
static const int N=12;
int num[(1<<N)+7],p[N+7],n, ans;
inline void Swap(int i,int j,int k) {
int len=1<<k,si=(i-1)*len,sj=(j-1)*len;
for (ri l(1);l<=len;p(l)) swap(num[si+l],num[sj+l]);
}
inline int check(int x) {//用于判断交换后的块是否符合要求顺序递增
int len=1<<x;
for (ri i(1);i<=(1<<n-x);i+=2) if (num[i*len]+1!=num[i*len+1]) return 0;
return 1;
}
inline void dfs(int x,int cnt) {
if (x&&!check(x-1)) return;
if (x==n) {ans+=p[cnt];return;}
dfs(x+1,cnt);
ri ch[5],tot=0,len=1<<x;//一定不要设成全局数组,因为若要定义为全局,向下递归时分支会将他改变,之后回溯时会炸。
for (ri i(1);i<=(1<<n-x);i+=2) {
if (num[i*len]+1!=num[i*len+1]) {
if (tot==4) return;
ch[p(tot)]=i;ch[p(tot)]=i+1;
}
}
if (!tot) return;
for (ri i(1);i<=tot;p(i)) {
for (ri j(i+1);j<=tot;p(j)) {
// if ((i+j==3||i+j==7)&&tot==4) continue;
Swap(ch[i],ch[j],x);
dfs(x+1,cnt+1);
Swap(ch[i],ch[j],x);//记得回溯
}
}
}
inline int main() {
// freopen("1.in","r",stdin);
n=read();
p[1]=1;
for (ri i(2);i<=12;p(i)) p[i]=p[i-1]*i;
for (ri i(1);i<=(1<<n);p(i)) num[i]=read();
dfs(0,0);
printf("%d\n",ans);
return 0;
}
}
int main() {return nanfeng::main();}

目前是洛谷最优解,而且这么写码量也很小。

题解 P3322 [SDOI2015]排序的更多相关文章

  1. [洛谷P3322] SDOI2015 排序

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

  2. 【LG3322】[SDOI2015]排序

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

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

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

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

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

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

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

  6. 【题解】SDOI2015序列统计

    [题解]SDOI2015序列统计 来自永不AFO的YYB的推荐 这里是乘积,比较麻烦,不过由于给定的序列膜数是个小质数,所以可以\(O(m^2\log m)\)找原跟(实际上不需要这么多). 乘积有点 ...

  7. SDOI2015 排序

    SDOI2015 排序 今天看到这道题,没有一点思路,暴力都没的打...还是理解错题意了,操作不同位置不是说改不同的区间,而是不同操作的顺序...考场上如果知道这个的话最少暴力拿一半啊,因为正解本来就 ...

  8. [SDOI2015]排序 题解 (搜索)

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

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

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

随机推荐

  1. 【源码篇】Flutter GetX深度剖析 | 我们终将走出自己的路(万字图文)

    前言 人心中的成见是一座大山,任你怎么努力都休想搬动. 这是电影<哪吒>里申公豹说的一句话,也是贯彻整部电影的一个主题:或许这句话引起了太多人的共鸣:35岁职场危机,大厂卡本科学历,无房无 ...

  2. 浅谈C++11中的多线程(二)

    摘要 本篇文章围绕以下几个问题展开: 进程和线程的区别 何为并发?C++中如何解决并发问题?C++中多线程的基本操作 浅谈C++11中的多线程(一) - 唯有自己强大 - 博客园 (cnblogs.c ...

  3. C#版Nebula客户端编译

    一.需求背景 从Nebula的Github上可以发现,Nebula为以下语言提供了客户端SDK: nebula-cpp nebula-java nebula-go nebula-python nebu ...

  4. chown、chgrp 改变所有者、所属组

    chown [option] [所有者][:[所属组]] file... chown指定文件的拥有者或者所属组,可以通过用户名或者用户id.组名.组id来修改,同时可以修改多个文件,文件以空格分割,支 ...

  5. C++泛型编程-举例

    就是C++里面说的函数模板和类模板,我们以前写C语言的时候,不同的类型参数,可能要写不同的函数. C++的模板出现之后,就可以实现函数模板,函数模板可以接纳不同的类型,然后这些类型都可以调用同一个函数 ...

  6. vue3如何编写挂载DOM的插件

    vue3 跟 vue2 相比,多了一个 app 的概念,vue3 项目的创建也变成了 // main.jsimport { createApp } from 'vue' import App from ...

  7. python 连接远程服务器,修改时间

    import paramiko from datetime import date, timedelta def set_time(hostname): ssh = paramiko.SSHClien ...

  8. [考试总结]noip模拟22

    又发现模拟 \(22\) 的总结也咕掉了,现在补上它... 似乎又是gg的一场. 以为自己的部分分数打的很全,然而到后面发现自己的树剖打假了 \(\color{green}{\huge{\text{树 ...

  9. 【原创】case、casez和casex谁是谁

    在Verilog中case语句经常用于多分支表决的结构,case后的表达式会与各分支表达式"全等"那么对应的分支会被执行.其基本结构如下: case(expression) exp ...

  10. Spring Cloud分区发布实践(3) 网关和负载均衡

    注意: 因为涉及到配置测试切换, 中间环节需按此文章操作体验, 代码仓库里面的只有最后一步的代码 准备好了微服务, 那我们就来看看网关+负载均衡如何一起工作 新建一个模块hello-gateway, ...