此题一看就有点像快排,先对最小一层操作,逐次向上,直到完成。
考虑如何操作,对于每一层(长度为2^x),暴力找出每段是否排好序,如果不是,num++,
对于每一层,如果num>2显然无解,因为上一层已经排好,将其分成两段,暴力调换,如果可以,继续枚举
最后发现操作顺序无关(显然),每次加上操作数的阶乘
太暴力了,没什么优化
#include <cstdio> using namespace std; int n,num,ans; int bin[15]={1},kk[15]={1},a[5000]; int sum; bool check(int l,int r) { if (l==r) return 1; for (int i=l+1;i<=r;i++) if (a[i]<a[i-1] || a[i]-a[i-1]>1) return 0; return 1; } bool swap(int l,int h,int ln) { int b[5000]; for (int i=0;i<ln;i++) b[i]=a[l+i]; for (int i=0;i<ln;i++) a[l+i]=a[h+i]; for (int i=0;i<ln;i++) a[h+i]=b[i]; } void dfs(int x) { int nu=0;int p[100]; for (int i=1;i<=bin[n];i+=bin[x]) { if (!check(i,i+bin[x]-1)) p[++nu]=i,p[++nu]=i+bin[x-1]; } if (nu>4) return; if (nu==0) { if (x!=n) dfs(x+1); else ans+=kk[sum]; } else if (nu==2) { sum++; swap(p[1],p[2],bin[x-1]); if (check(p[1],p[1]+bin[x]-1)) { if (x==n) ans+=kk[sum]; else dfs(x+1); } sum--; swap(p[1],p[2],bin[x-1]); return; } else if (nu==4) { sum++; for (int i=1;i<=2;i++) for (int j=3;j<=4;j++) { swap(p[i],p[j],bin[x-1]); if (check(p[1],p[1]+bin[x-1]-1) && check(p[3],p[3]+bin[x-1]-1)) { if (x==n) ans+=kk[sum]; else dfs(x+1); } swap(p[i],p[j],bin[x-1]); } sum--; } } int main () { // freopen("hh.in","r",stdin); scanf("%d",&n); for (int i=1;i<=n;i++) bin[i]=bin[i-1]*2,kk[i]=kk[i-1]*i; for (int i=1;i<=bin[n];i++) scanf ("%d",&a[i]); dfs(1); printf("%d",ans); }