zoukankan      html  css  js  c++  java
  • BZOJ 3990: [SDOI2015]排序 [搜索]

    3990: [SDOI2015]排序

    题意:(2^n)的一个排列,给你n种操作,第i种把每(2^{i-1})个数看成一段,交换任意两段。问是这个序列有序的操作方案数,两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同).


    R1D1T1

    先玩一下样例

    发现操作的顺序其实没有影响

    从小到大考虑,设当前处理的有n段,可以分成(frac{n}{2})个二元组((a_i, a_{i+1})),每个都要满足(a_i +1 = a_{i+1}),找出有几个不满足,如果(le 2)个那么枚举如何交换然后再处理(frac{n}{2})段的时候

    注意每种成立的交换就要继续搜索...一开始没这么做然后35分...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=(1<<12) + 5, INF=1e9+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int bin, n, t[15][N], fac[N]; ll ans=0;
    inline bool check(int *a, int x, int y) {return a[x]+1 == a[x+1] && a[y]+1 == a[y+1];}
    inline void ready(int *a, int n) {
    	for(int i=1; i<=n; i++) a[i] = a[i*2-1]/2 + 1;
    }
    void dfs(int d, int n, int now) { //printf("dfs %d %d  %d
    ",d,n,now);
    	if(d>=bin) {ans += fac[now]; return;}
    	int *a = t[d], *b = t[d+1];
    	//for(int i=1; i<=n; i++) printf("%d ",a[i]); puts(" a");
    
    	int tot=0, li[5];
    	for(int i=1; i<=n; i+=2) 
    		if(a[i]+1 != a[i+1]) {li[++tot]=i; if(tot>2) return;}
    
    	int x=li[1], y=li[2];
    	if(tot==2) {
    		swap(a[x], a[y]);
    		if(check(a, x, y)) memcpy(b, a, sizeof(int)*(n+1)), ready(b, n>>1), dfs(d+1, n>>1, now+1); 
    		swap(a[x], a[y]);
    
    		swap(a[x], a[y+1]);
    		if(check(a, x, y)) memcpy(b, a, sizeof(int)*(n+1)), ready(b, n>>1), dfs(d+1, n>>1, now+1); 
    		swap(a[x], a[y+1]);
    
    		swap(a[x+1], a[y]);
    		if(check(a, x, y)) memcpy(b, a, sizeof(int)*(n+1)), ready(b, n>>1), dfs(d+1, n>>1, now+1); 
    		swap(a[x+1], a[y]);
    
    		swap(a[x+1], a[y+1]);
    		if(check(a, x, y)) memcpy(b, a, sizeof(int)*(n+1)), ready(b, n>>1), dfs(d+1, n>>1, now+1); 
    		swap(a[x+1], a[y+1]);
    	} else if(tot==0) memcpy(b, a, sizeof(int)*(n+1)), ready(b, n>>1), dfs(d+1, n>>1, now);
    	else if(tot==1) swap(a[x], a[x+1]), memcpy(b, a, sizeof(int)*(n+1)), ready(b, n>>1), dfs(d+1, n>>1, now+1);
    }
    int main() {
    	freopen("in","r",stdin);
    	bin=read(); n=1<<bin;
    	fac[0]=1;
    	for(int i=1; i<=bin; i++) fac[i]=fac[i-1]*i;
    	for(int i=1; i<=n; i++) t[0][i]=read();
    	dfs(0, n, 0);
    	printf("%lld", ans);
    }
    
    
  • 相关阅读:
    jfreechart简单介绍---曲线图
    Java监听器
    在java里actionPerformed是做什么用的
    sqlserver,oracle,mysql等的driver驱动,url怎么写
    ibatis入门实例(完整)
    java连接access数据库的三种方式以及远程连接
    elementui入门以及nodeJS环境搭建
    vue路由
    vue模板语法下
    vue模板语法上
  • 原文地址:https://www.cnblogs.com/candy99/p/6675533.html
Copyright © 2011-2022 走看看