SDOI2015 排序

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

DFS

题目问的是方案数,如果操作确定了是谁的话顺序是无所谓的,压一个A(n n)加上就好。这一点很显然,不管怎么移动,如果先一后二可以,那么先二后一也是可以的。找规律就好。

现在需要做的是找到不同的操作序列,这里的不同不是指顺序,而是指种类。因为上面说了顺序无影响,那我们可以从最小的开始,能换就换,说白了就是暴搜%%%XIN队。

暴搜的话肯定要砍大树的,上面的思路如果大力搞的话必暴,其实在枚举序列找不满足递增顺序的区间时,如果区间数>2了,直接return。因为每种操作只有一次,一次肯定换不了两个以上的区间。如果没有不满足递增的区间,说明不需要这个操作,直接整一个DFS(x+1,num){x代表当前是第几个操作,num表示用了几个操作。}如果只有一个,那就自己换一下就OK。如果有两个,那么自己跟自己块里的两段肯定不能换,因为还有另一个块不合法,自己换了那人家怎么办。所以是2×2,枚举去换,换了后检查合法性如果合法就DFS(x+1,num+1)否则不用管。还有记得回溯的时候把换了的再给人换回去

。这样这道题就AC了。

不过苣蒻还是不懂玄学复杂度,明明是2^24,虽然远远达不到这个水平,但也不至于40ms就跑完了吧,一个点才2ms,这不是a+b的时间吗哈哈。

code有些冗长了,四种情况其实可以写函数的,我直接摆在那了,反正也是打一个然后复制粘贴,不过我好像改变量时少改了一个,调了好长时间。。算了,懒得改代码了,就这样吧。

#include<bits/stdc++.h>
using namespace std;
int n,a[1000101],ans=0;
inline void fr(){freopen("c.in","r",stdin);}
inline void sc(){scanf("%d",&n);}
namespace AYX
{ inline void dfs(int x,int num)
{ if(x==n+1)
{ int l=1;
for(int i=num;i;--i)
l*=i;
ans+=l;
return;
}
int len=(1<<(x)),kk=(1<<(x-1)),m1,m2,cnt=0;
for(int i=1;i<=(1<<n)-len+1;i+=len)
{ for(int j=i;j<(1<<x)/2+i;++j)
{ if(a[j]+kk!=a[j+kk])
{ ++cnt;
if(cnt==1)
m1=i;
else
m2=i;
break;
}
if(cnt>2)return;
}
}
if(cnt>2)return;
if(cnt==0)
{ dfs(x+1,num);
return ;
}
if(cnt==1)
{
for(int i=m1;i<=m1+kk-1;++i)
swap(a[i],a[i+kk]);
dfs(x+1,num+1);
for(int i=m1;i<=m1+kk-1;++i)
swap(a[i],a[i+kk]);
return;
}
bool bo=0;
int mm1=m1+kk,mm2=m2+kk;
for(int i=1;i<=kk;++i)
swap(a[i+m1-1],a[m2+i-1]);
for(int i=1;i<=kk;++i)
{ if(a[i+m1-1]+kk!=a[i+m1+kk-1] or a[i+m2-1]+kk!=a[i+m2+kk-1])
{
bo=1;break;
}
}
if(!bo)dfs(x+1,num+1);
for(int i=1;i<=kk;++i)
swap(a[i+m1-1],a[m2+i-1]);
bo=0;
for(int i=1;i<=kk;++i)
swap(a[i+mm1-1],a[m2+i-1]);
for(int i=1;i<=kk;++i)
{ if(a[i+m1-1]+kk!=a[i+m1+kk-1] or a[i+m2-1]+kk!=a[i+m2+kk-1])
{
bo=1;break;
}
}
if(!bo)dfs(x+1,num+1);
for(int i=1;i<=kk;++i)
swap(a[i+mm1-1],a[m2+i-1]);
bo=0;
for(int i=1;i<=kk;++i)
swap(a[i+m1-1],a[mm2+i-1]);
for(int i=1;i<=kk;++i)
{ if(a[i+m1-1]+kk!=a[i+m1+kk-1] or a[i+m2-1]+kk!=a[i+m2+kk-1])
{
bo=1;break;
}
}
if(!bo)dfs(x+1,num+1);
for(int i=1;i<=kk;++i)
swap(a[i+m1-1],a[mm2+i-1]);
bo=0;
for(int i=1;i<=kk;++i)
swap(a[i+mm1-1],a[mm2+i-1]);
for(int i=1;i<=kk;++i)
{ if(a[i+m1-1]+kk!=a[i+m1+kk-1] or a[i+m2-1]+kk!=a[i+m2+kk-1])
{
bo=1;break;
}
}
if(!bo)dfs(x+1,num+1);
for(int i=1;i<=kk;++i)
swap(a[i+mm1-1],a[mm2+i-1]);
}
inline void work()
{ for(int i=1;i<=(1<<n);++i)scanf("%d",&a[i]);
dfs(1,0);printf("%d\n",ans);
}
inline short main()
{sc();work();return 0;}
}
signed main()
{return AYX::main();}

SDOI2015 排序的更多相关文章

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

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

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

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

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

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

  4. 【LG3322】[SDOI2015]排序

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

  5. Bzoj3990 [SDOI2015]排序

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

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

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

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

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

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

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

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

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

随机推荐

  1. Qt event()

    event() 今天要说的是 event()函数.记得之前曾经提到过这个函数,说在事件对象创建完毕后,Qt 将这个事件对象传递给 QObject的 event()函数.event()函数并不直接处理事 ...

  2. LeetCode42. 接雨水(java)

    42.接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种 ...

  3. 回忆java输入输出流,走出误区

    input read 将一个XXX读入(input)---从输入流中读取数据的下一个字节(code操作的).output write 将一个类型的数据写入此流(code操作的)---然后把XXX输出( ...

  4. C# - 音乐小闹钟_BetaV3.0

    时间:2017-11-22 作者:byzqy 介绍: 音乐小闹钟 BetaV3.0 新鲜出炉了,快来围观吧!上效果图: 是不是觉得顿时变得高大上了许多呢?^_^ 工具/原料: (操作系统:Window ...

  5. dotnet OpenXML 读取 PPT 内嵌 ole 格式 Excel 表格的信息

    在 Office 中,可以在 PPT 里面插入表格,插入表格有好多不同的方法,对应 OpenXML 文档存储的更多不同的方式.本文来介绍如何读取 PPT 内嵌 ole 格式的 xls+ 表格的方法 在 ...

  6. vue 上传头像悬浮显示文字

    template部分: 头像外部加一个 div <div class="user-info-head"> </div>   css 部分 <style ...

  7. vue element-ui el-date-picker 数据可以更改,但是前端不显示的更改后的数据问题

    template: <el-form-item label="有效时间:" prop="validTime">                    ...

  8. netty系列之:搭建HTTP上传文件服务器

    目录 简介 GET方法上传数据 POST方法上传数据 POST方法上传文件 总结 简介 上一篇的文章中,我们讲到了如何从HTTP服务器中下载文件,和搭建下载文件服务器应该注意的问题,使用的GET方法. ...

  9. chrome插件开发学习(一)

    两个不错的网址: 360chrome插件开发文档:http://open.chrome.360.cn/extension_dev/manifest.html 图灵 chrome插件开发于应用 电子书: ...

  10. CentOS 7操作系统安装

    1.关于运维小伙伴可以采用何种方式安装操作系统 下面列举的只是我会用到的安装方式,在运维过程中并不一定是最优解,只是自己运维过程中的一些经验. (1)物理服务器,可以通过连接管理口来安装操作系统,管理 ...