BZOJ3990:[SDOI2015]排序——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3990
小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].
考虑暴力怎么写……不会啊。
我们能知道实际上操作顺序不影响结果,于是我们大可以从1~n枚举操作做。
因为最终变得有序,所以我们可以对于每一“大块”查询是否已经排好序了,如果没排好,就说明这一“大块”里的两小块肯定是放错位置的。
如果这样的小块<=4的话我们还好办,显然是前一“大块”的其中一“小块”和后一“大块”的其中一“小块”交换位置。
如果<=2那么就这两块交换就行了。
如果>4我们就处理不了了。
#include<map> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<vector> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1<<13; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } int n,m,a[N]; ll jc[N],ans; bool pan(int l,int r){ for(int i=l;i<r;i++) if(a[i]+1!=a[i+1])return 0; return 1; } void mdy(int l,int r,int k){ for(int i=l,j=r;i<l+(1<<k);i++,j++) swap(a[i],a[j]); } void dfs(int l,int num){ if(l>n){ ans+=jc[num]; return; } int tmp[4],tot=0; for(int i=1;i<=m;i+=(1<<l)) if(!pan(i,i+(1<<l)-1)){ tmp[++tot]=i; if(tot>2)return; } if(!tot){dfs(l+1,num);return;} else if(tot==1){ mdy(tmp[1],tmp[1]+(1<<l-1),l-1); if(pan(tmp[1],tmp[1]+(1<<l-1)))dfs(l+1,num+1); mdy(tmp[1],tmp[1]+(1<<l-1),l-1); }else{ for(int i=0;i<=1;i++) for(int j=0;j<=1;j++){ mdy(tmp[1]+(i<<(l-1)),tmp[2]+(j<<(l-1)),l-1); if(pan(tmp[1],tmp[1]+(1<<l-1))&& pan(tmp[2],tmp[2]+(1<<l-1)))dfs(l+1,num+1); mdy(tmp[1]+(i<<(l-1)),tmp[2]+(j<<(l-1)),l-1); } } } int main(){ n=read(),m=1<<n; jc[0]=1;for(int i=1;i<=n;i++)jc[i]=jc[i-1]*i; for(int i=1;i<=m;i++)a[i]=read(); dfs(1,0); printf("%lld\n",ans); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++