题目:
小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].
分析:
首先由这样的一个性质,一个合法序列的操作的任意排列都合法,因为对于任意两个动作先执行哪一个产生的结果都一样(大范围的交换,对小范围内的点得相对位置没有影响)
再多说一句,这个内部是很重要的,与长为8的数组, 划分成4 ,4 ,其他层面的改变都是对4,4 内部的改变与4 ,4 的先对位置无关,所以具有无序性。
那么只需确定从大到小或从小到大枚举操作即可。
对于每次的处理,可以看成这样例如
8
7 8 5 6 1 2 4 3 那么对于第一种交换需要解决的问题是吧所有的段变成12 34 56 78 这样四个段,他们的顺序无所谓,因为只有该操作可以做到这一点。这样先统计有多少小段
内的两个数不是 递增且相差1的关系。那么多与2个显然没有解,进行可行性枚举,就直接过了此题。
分析:
首先由这样的一个性质,一个合法序列的操作的任意排列都合法,因为对于任意两个动作先执行哪一个产生的结果都一样(大范围的交换,对小范围内的点得相对位置没有影响)
再多说一句,这个内部是很重要的,与长为8的数组, 划分成4 ,4 ,其他层面的改变都是对4,4 内部的改变与4 ,4 的先对位置无关,所以具有无序性。
那么只需确定从大到小或从小到大枚举操作即可。
对于每次的处理,可以看成这样例如
8
7 8 5 6 1 2 4 3 那么对于第一种交换需要解决的问题是吧所有的段变成12 34 56 78 这样四个段,他们的顺序无所谓,因为只有该操作可以做到这一点。这样先统计有多少小段
内的两个数不是 递增且相差1的关系。那么多与2个显然没有解,进行可行性枚举,就直接过了此题。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <set> #include <map> #include <string> #include <list> #include <cstdlib> #include <queue> #include <stack> #include <cmath> #include <bitset> #include <cassert> #define ALL(a) a.begin(), a.end() #define clr(a, x) memset(a, x, sizeof a) #define X first #define Y second #define pb push_back #define lowbit(x) (x&(-x)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep1(i,x,y) for(int i=x;i<=y;i++) #define rep(i,n) for(int i=0;i<(int)n;i++) using namespace std; const double eps = 1e-10; typedef long long LL; typedef long long ll; typedef pair<int, int> pii; const int oo =0x3f3f3f3f; const int N = (1<<12)+10; int id[N] , n , aa[N] , now[N] , ans , ji[30]; void dfs(int d,vector<int> a , int all){ if(d == n+1){ ans += ji[all]; return ; } int cnt = 0, po[3]; for(int i=1 , j=1;i<a.size();i+=2,j++){ id[i+1] = j; if(a[i-1]+1 != a[i]){ if(cnt == 2) return ; po[++cnt] = i; } } vector<int> te; if(!cnt){ for(int i=1;i<a.size();i+=2) te.push_back(id[a[i]]); dfs(d+1,te,all); return ; } if(cnt == 1){ int j = po[1]; swap(a[j],a[j-1]); for(int i=1;i<a.size();i+=2) te.push_back(id[a[i]]); dfs(d+1,te,all+1); return ; } for(int i=-1;i<=0;i++) for(int j=-1;j<=0;j++){ int pi = po[1]+i , pj = po[2]+j; swap(a[pi],a[pj]); if(a[po[1]-1]+1 == a[po[1]] && a[po[2]-1]+1 == a[po[2]]){ te.clear(); for(int i=1;i<a.size();i+=2) te.push_back(id[a[i]]); dfs(d+1,te , all+1); } swap(a[pi],a[pj]); } } int main() { ji[0]=1; for(int i=1;i<=12;i++) ji[i] = ji[i-1]*i; scanf("%d",&n); vector<int> an; rep1(i,1,(1<<n)) scanf("%d",&aa[i]) , now[i] = aa[i] , an.push_back(aa[i]); ans = 0; dfs(1 , an , 0); cout<<ans<<endl; return 0; }