[洛谷P3322] SDOI2015 排序

问题描述

小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].

输入格式

第一行,一个整数N第二行,2^N个整数,A[1..2^N]。

输出格式

一个整数表示答案

样例输入

3
7 8 5 6 1 2 4 3

样例输出

6

数据范围

100%的数据, 1<=N<=12.

解析

首先可以想到的是每次排序交换的两个块中一定是有序的,那么我们从小到大讨论每一种操作,如果对于第\(i\)种操作,序列每个长度为\(2^{i-1}\)的块都是有序的,那么就看长度为\(2^i\)的块有哪些不是单调递增的。如果不满足要求的块的数量大于2,就无解。否则若数量为1,就交换那一块的两半;数量为2就分4部分两两交换。至于有序的判断,可以用排列的性质,如果块最右边的值减去最左边的值等于块长,说明有序。

另外,对于一个操作序列,任意交换两个元素是没有影响的,所以每找到一个长为\(n\)的操作序列,都要增加\(n!\)中方案。

代码

#include <iostream>
#include <cstdio>
#define N 5000
using namespace std;
int n=1,m,i,a[N];
long long ans,f[N];
int read()
{
    char c=getchar();
    int w=0;
    while(c<'0'||c>'9') c=getchar();
    while(c<='9'&&c>='0'){
        w=w*10+c-'0';
        c=getchar();
    }
    return w;
}
void dfs(int x,int sum)
{
    int gap=(1<<(x-1)),gap1=gap<<1;
    for(int i=1;i<=n&&x>1;i+=gap){
        if(a[i+gap-1]-a[i]!=gap-1) return;
    }
    if(x==m+1){
        ans+=f[sum];
        return;
    }
    dfs(x+1,sum);
    int op[5],cnt=0;
    for(int i=1;i<=n;i+=gap1){
        int j=(2*i+gap1-1)/2+1;
        if(a[i+gap1-1]-a[i]!=gap1-1){
            op[++cnt]=i;
            op[++cnt]=j;
        }
    }
    if(cnt>4) return;
    for(int i=1;i<=cnt;i++){
        for(int j=i+1;j<=cnt;j++){
            for(int k=0;k<gap;k++) swap(a[op[i]+k],a[op[j]+k]);
            dfs(x+1,sum+1);
            for(int k=0;k<gap;k++) swap(a[op[i]+k],a[op[j]+k]);
        }
    }
}
int main()
{
    m=read();
    for(i=1;i<=m;i++) n*=2;
    f[0]=1;
    for(i=1;i<=12;i++) f[i]=f[i-1]*i;
    for(i=1;i<=n;i++) a[i]=read();
    dfs(1,0);
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LSlzf/p/11873089.html