【搜索】BZOJ 3990: 【Sdoi 2015】排序
来源:互联网 发布:北部战区山东知乎 编辑:程序博客网 时间:2024/05/17 07:03
3990: [SDOI2015]排序
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 336 Solved: 164
[Submit][Status][Discuss]
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
7 8 5 6 1 2 4 3
Sample Output
6
网上题解都看不懂。。
只能%hzwer代码。
黄学长:
每种交换只能用一次。
我们从小到大DFS,对于第i次操作我们将序列分成2^(n-i)段,每段长度2^i
我们找到序列中不是连续递增的段,如果这样的段超过2个,显然就废了
如果没有这样的段,就不需要执行这个操作
如果有一个这样的段,判断将这个段的前半部分和后半部分交换后是否连续递增,如果是就交换然后继续DFS
如果有两个这样的段,判断四种交换情况然后DFS
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 6 using namespace std; 7 8 int a[4098],n; 9 10 long long fac[14],ans=0;11 12 void init(){fac[1]=1;for(int i=2;i<=n;i++)fac[i]=fac[i-1]*i;}13 14 int read()15 {16 int x=0;char ch=getchar();17 while(ch<'0'||ch>'9')ch=getchar();18 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();19 return x;20 }21 22 void swap(int x,int y,int nu)23 {24 for(int i=x,j=y,nn=0;nn<nu;nn++)25 swap(a[i+nn],a[j+nn]);26 }27 28 void DFS(int dep,int sco)29 {30 if(dep==n)31 {32 ans+=fac[sco];33 return;34 }35 int temp=1<<(dep+1),stack[4]={0,0,0,0},top=0;36 for(int i=1;i<(1<<n);i+=temp)37 {38 if(a[i+(temp>>1)-1]+1!=a[i+(temp>>1)])stack[++top]=i+(temp>>1)-1;39 if(top>2)return;40 }41 if(top==0)42 {43 DFS(dep+1,sco);44 return;45 }46 else if(top==1)47 {48 if(a[stack[1]-(temp>>1)+1]!=a[stack[1]+(temp>>1)]+1)return;49 swap(stack[top]-(temp>>1)+1,stack[top]+1,temp>>1);50 DFS(dep+1,sco+1);51 swap(stack[top]-(temp>>1)+1,stack[top]+1,temp>>1);52 return;53 }54 else55 {56 if(a[stack[1]]+1==a[stack[2]+1]&&a[stack[2]]+1==a[stack[1]+1])57 {58 swap(stack[1]-(temp>>1)+1,stack[2]-(temp>>1)+1,temp>>1);59 DFS(dep+1,sco+1);60 swap(stack[1]-(temp>>1)+1,stack[2]-(temp>>1)+1,temp>>1);61 swap(stack[1]+1,stack[2]+1,temp>>1);62 DFS(dep+1,sco+1);63 swap(stack[1]+1,stack[2]+1,temp>>1);64 }65 else if(a[stack[1]]+1==a[stack[2]-(temp>>1)+1]&&a[stack[1]+(temp>>1)]+1==a[stack[2]+1])66 {67 swap(stack[1]+1,stack[2]-(temp>>1)+1,temp>>1);68 DFS(dep+1,sco+1);69 swap(stack[1]+1,stack[2]-(temp>>1)+1,temp>>1);70 }71 else if(a[stack[2]]+1==a[stack[1]-(temp>>1)+1]&&a[stack[2]+(temp>>1)]+1==a[stack[1]+1])72 {73 swap(stack[2]+1,stack[1]-(temp>>1)+1,temp>>1);74 DFS(dep+1,sco+1);75 swap(stack[2]+1,stack[1]-(temp>>1)+1,temp>>1);76 }77 return;78 }79 }80 81 int main()82 {83 n=read();84 init();85 for(int i=1;i<=(1<<n);i++)86 a[i]=read();87 DFS(0,0);88 printf("%lld",ans);89 return 0;90 }
0 0
- 【搜索】BZOJ 3990: 【Sdoi 2015】排序
- 【SDOI 2015】【BZOJ 3994】约数个数和
- [BZOJ]3991 [SDOI]2015 寻宝游戏 虚树
- [BZOJ 3994][SDOI 2015]约数个数 数学+反演
- BZOJ 3993 [SDOI 2015] 网络流+二分答案 解题报告
- HDU 5499:SDOI【排序】
- 【BZOJ 2190】【SDOI 2008】仪仗队
- BZOJ 3531 SDOI 2014 旅行
- sdoi 2014 旅行 bzoj 3531
- BZOJ 2726 SDOI 任务安排
- 【BZOJ 4513】【SDOI 2016】储能表
- BZOJ 3991 SDOI 2015 寻宝游戏(异象石) LCA + Set + DFS序
- BZOJ 3992 SDOI 2015 序列统计 NTT 生成函数 计数 原根
- BZOJ 2190 SDOI 2008 仪仗队 线性欧拉筛
- 【BZOJ】 2049 SDOI洞穴探险 【乱搞】
- 【BZOJ 1925】【SDOI 2010】地精部落
- 【SDOI 2013】【BZOJ 3130】费用流
- 【枚举】【SDOI 2011】【bzoj 2241】打地鼠
- 响应式网站设计与制作
- 小爬虫1.0
- 14:类初步使用
- 优惠码,开启了您的奖学金征程
- AngularJS基础——MVC、$scope的作用域、依赖注入的代码压缩以及run方法
- 【搜索】BZOJ 3990: 【Sdoi 2015】排序
- CocoaPods安装和使用教程
- 浅谈MVC架构模式
- 禁止在窗口界面线程中进行线程同步或进行耗时的操作。。。
- IE浏览器提示代理服务器没有响应,但是360浏览器可以用
- Android通过get,post方式客户端与服务器端交互实例(慕课网笔记)
- 解救MacBook Pro老电脑显卡
- Yii2.0入门--安装方法及目录结构
- C++数学计算库与软件