题解思路:因为可以看出互换顺序跟互换方法无关,所以我们找出一种方法答案就加上使用方法长度的阶乘。
分析:
最终要获得排列好的序列要么是以下两种形式
或者1 2 3 ... 2^n
2^(n-1)+1...2^n 1 2 .. 2^(n-1)
然后往前推你会发现我们要得到能排列好的序列在第i次操作中必须能变出每段长度2^(i+1)序列都是连续递增的否则就不可能排列好
那么我当有1段不满足条件的时候直接从中间切开然后两段互换
如果有两段不满足条件的时候尝试2种互换方法即可
如果有三段以上不满足条件那么不用看了肯定换不出来排序好的。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = (1<<12)+5;
vector<int>v;
int n;
ll ans = 0;
ll fac(int n){
ll ans = 1;
while(n){
ans = ans*n;
n--;
}
return ans;
}
void dfs(int i,int len){
if(i==n){
for(int i = 0; i < v.size(); i++)
if(v[i]!=i+1)
return ;
ans+=fac(len);
return;
}
int d = 1<<(i+1);
int f = 1<<i;
vector<int>fa;
vector<int>a,b;
fa.push_back(-1);
for(int j = 0; j < v.size(); j+=d)
for(int k = 1; k < d; k++)
if(v[j+k]!=v[j+k-1]+1){
if(k%f)
return;
if(fa[fa.size()-1]!=j)
fa.push_back(j);
}
if(fa.size()==1)
dfs(i+1,len);
else if(fa.size()==2){
int l = fa[1],r = fa[1]+f;
for(int k = 0; k < f; k++)
swap(v[l+k],v[r+k]);
dfs(i+1,len+1);
for(int k = 0; k < f; k++)
swap(v[l+k],v[r+k]);
}
else if(fa.size()==3){
a.push_back(v[fa[1]]);
a.push_back(v[fa[1]+f]);
a.push_back(v[fa[2]]);
a.push_back(v[fa[2]+f]);
b = a;
sort(b.begin(),b.end());
int l,r;
if((a[0]==b[0]||a[1]==b[1])&&(a[2]==b[2]||a[3]==b[3])){
if(a[0]!=b[0])
l = fa[1];
else
l = fa[1]+f;
if(a[2]!=b[2])
r = fa[2];
else
r = fa[2]+f;
for(int k = 0; k < f; k++)
swap(v[l+k],v[r+k]);
dfs(i+1,len+1);
for(int k = 0; k < f; k++)
swap(v[l+k],v[r+k]);
}
if((a[2]==b[0]||a[3]==b[1])&&(a[0]==b[2]||a[1]==b[3])){
if(a[0]!=b[2])
l = fa[1];
else
l = fa[1]+f;
if(a[2]!=b[0])
r = fa[2];
else
r = fa[2]+f;
for(int k = 0; k < f; k++)
swap(v[l+k],v[r+k]);
dfs(i+1,len+1);
for(int k = 0; k < f; k++)
swap(v[l+k],v[r+k]);
}
}
else
return;
}
int main(){
scanf("%d",&n);
v.resize(1<<n);
for(int i = 0; i < (1<<n); i++)
scanf("%d",&v[i]);
dfs(0,0);
printf("%lld\n",ans);
return 0;
}