大爆搜
操作不分先后,所以我们就枚举每一个操作
我们从1开始枚举区间个数为i
因为只能交换1<
#include<cstdio>
#include<iostream>
using namespace std;
int jc[14],base[14],n,a[1<<13];long long ans;
bool check(int x,int t){
for(int i=1;i<base[t];i++)
if(a[x+i]!=a[x+i-1]+1) return 0;
return 1;
}
void swap2(int x,int y,int t){
for(int i=0;i<base[t];i++)
swap(a[x+i],a[y+i]);
}
void dfs(int x,int t){
if(x==n+1) {ans+=jc[t];return ;}
int f1=0,f2=0;
for(int i=1;i<=base[n];i+=base[x])
if(!check(i,x)){
if(!f1) f1=i;
else if(!f2) f2=i;
else return ;
}
if(!f1&&!f2) dfs(x+1,t);
else if(!f2){
swap2(f1,f1+base[x-1],x-1);
dfs(x+1,t+1);
swap2(f1,f1+base[x-1],x-1);
}
else {
for(int i=0;i<=1;i++)
for(int y=0;y<=1;y++){
swap2(f1+i*base[x-1],f2+y*base[x-1],x-1);
if(check(f1,x)&&check(f2,x)){dfs(x+1,t+1);
swap2(f1+i*base[x-1],f2+y*base[x-1],x-1);break;
}
swap2(f1+i*base[x-1],f2+y*base[x-1],x-1);
}
}
}
int main(){
scanf("%d",&n);
jc[0]=1;
for(int i=1;i<=12;i++) jc[i]=jc[i-1]*i;
base[0]=1;
for(int i=1;i<=12;i++) base[i]=base[i-1]<<1;
for(int i=1;i<=base[n];i++) scanf("%d",&a[i]);
dfs(0,0);
printf("%lld",ans);
}