题意:
分析:
通过手玩样例 , 我们可以发现以下几条性质:
- 一个合法的操作序列,各个操作其实是互不影响的,也就是说,只要我们发现了一组合法的操作序列,那么它的全排列是都可以的
- 对于一种排列,有且仅有一种合法的操作集合,因为任意一类操作是无法通过别的其他操作等价替换的
那么我们将问题转化成了枚举操作集合,判断是否可行
然后我们发现从小到大进行每个操作,进行第 (i) 种操作后,情况合法当且仅当每 (2^{i-1}) 个数都是单调递增的
对于样例而言:
进行第一次操作后的合法情况应该是 :(7,8,5 ,6,1,2,3,4)
对于第 (i) 种操作,分情况讨论:
- 若没有需要操作的区间,跳过
- 若有一个需要操作的区间,直接修改
- 若有两个操作的区间,分 4 种情况进行修改
- 若有两个以上的区间不合法,则无解
代码:
#include<bits/stdc++.h>
using namespace std;
namespace zzc
{
inline long long read()
{
long long x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 4100;
long long n,ans;
long long a[maxn],pw[maxn],fac[maxn];
bool check(int x,int l)
{
for(int i=1;i<l;i++)
if(a[x+i]!=a[x+i-1]+1) return false;
return true;
}
void swap(int x,int y,int l)
{
for(int i=0;i<l;i++) std::swap(a[x+i],a[y+i]);
}
void dfs(int k,int num)
{
if(k>n)
{
ans+=fac[num];
return ;
}
int tmp1=0,tmp2=0;
for(int i=1;i<=pw[n];i+=pw[k])
{
if(!check(i,pw[k]))
{
if(!tmp1) tmp1=i;
else if(!tmp2) tmp2=i;
else return ;
}
}
if(!tmp1&&!tmp2) dfs(k+1,num);
else if(tmp1&&!tmp2)
{
swap(tmp1,tmp1+pw[k-1],pw[k-1]);
dfs(k+1,num+1);
swap(tmp1,tmp1+pw[k-1],pw[k-1]);
}
else
{
for(int x=0;x<=1;x++)
{
for(int y=0;y<=1;y++)
{
swap(tmp1+x*pw[k-1],tmp2+y*pw[k-1],pw[k-1]);
if(check(tmp1,pw[k])&&check(tmp2,pw[k])) dfs(k+1,num+1);
swap(tmp1+x*pw[k-1],tmp2+y*pw[k-1],pw[k-1]);
}
}
}
}
void work()
{
n=read();
fac[0]=pw[0]=1;
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i,pw[i]=pw[i-1]*2;
for(int i=1;i<=pw[n];i++) a[i]=read();
dfs(1,0);
printf("%lld
",ans);
}
}
int main()
{
zzc::work();
return 0;
}