您的位置:首页 > 其它

BZOJ3990 排序

2015-06-04 21:00 169 查看
题目:www.lydsy.com/JudgeOnline/problem.php?id=3990

这题很不错。

刚开始时无从下手,想了好多$O((2^n)log(2^n))$ 的idea,但是都不行。

后来去看题解发现操作序列是满足交换率的,然后竟然是搜索。

因为swap是swap的逆运算(歪歪的)

然后只要从小到大枚举操作序列就可以了。

这样类似分治下去,当你在计算长度为$2^i$的序列时已经保证了所有长度为$2^{i-1}$的序列的「连续且递增」。

注意是「连续且递增」,开始W了好多发,然后推掉重写(开抄) 呜呜。

好像可以证明是$O(n \cdot 2^{2n})$ ?

以后见到这种操作数很小的题目要想想搜索,就算是暴力也可以多拿分。

#include <cstdio>
#include <cstring>
#include <vector>

#define LL long long
#define N 13

using namespace std;

int n;
LL fact[21],ans;

void change(vector<int> &x,int l1,int l2,int len){
for(int i=0;i<len;i++)
swap(x[l1+i],x[l2+i]);
}

bool check(vector<int> x,int l,int len){
for(int i=1;i<len;i++)
if(x[l+i]!=x[l+i-1]+1) return 0;
return 1;
}

void dfs(vector<int> x,int t,int now){
if(t==n){
ans+=fact[now];
return;
}
int tot=0,a[5];
for(int i=0;i<(1<<n);i+=(1<<(t+1)))
if(!check(x,i,1<<(t+1))){
if(tot==4) return;
a[++tot]=i; a[++tot]=i+(1<<t);
}
vector<int> b;
if(!tot) dfs(x,t+1,now);
if(tot==2){
if(x[a[2]]+(1<<t)==x[a[1]]){
b=x;
change(b,a[1],a[2],1<<t);
dfs(b,t+1,now+1);
}
}
if(tot==4){
if(x[a[1]]+(1<<t)==x[a[3]] && x[a[2]]+(1<<t)==x[a[4]]){
b=x;
change(b,a[2],a[3],1<<t);
dfs(b,t+1,now+1);
}
if(x[a[1]]+(1<<t)==x[a[4]] && x[a[3]]+(1<<t)==x[a[2]]){
b=x;
change(b,a[2],a[4],1<<t);
dfs(b,t+1,now+1);
}
if(x[a[3]]+(1<<t)==x[a[2]] && x[a[1]]+(1<<t)==x[a[4]]){
b=x;
change(b,a[1],a[3],1<<t);
dfs(b,t+1,now+1);
}
if(x[a[4]]+(1<<t)==x[a[2]] && x[a[3]]+(1<<t)==x[a[1]]){
b=x;
change(b,a[1],a[4],1<<t);
dfs(b,t+1,now+1);
}
}
}

vector<int> a;

int main(){
scanf("%d",&n);
a.resize(1<<n);
for(int i=0;i<(1<<n);i++) scanf("%d",&a[i]);
fact[0]=1;
for(int i=1;i<=18;i++) fact[i]=fact[i-1]*(LL)i;
dfs(a,0,0);
printf("%lld\n",ans);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: