【LG3322】[SDOI2015]排序

【LG3322】[SDOI2015]排序

题面

洛谷

题解

交换顺序显然不影响答案,所以每种本质不同的方案就给答案贡献次数的阶乘。

从小往大的交换每次至多\(4\)中决策,复杂度\(O(4^n)\)

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
using namespace std; 
const int MAX_N = 1 << 13; 
int N, a[MAX_N]; 
long long fac[13], ans; 
bool check(int x) { 
    for (int i = 1; i <= 1 << (N - x); i++) 
        if (a[(i - 1) * (1 << x) + 1] + (1 << (x - 1)) !=
            a[(i - 1) * (1 << x) + 1 + (1 << (x - 1))]) return 0; 
    return 1; 
} 
void Swap(int p1, int p2, int k) { 
    for (int i = 0; i < k; i++) 
        swap(a[p1 + i], a[p2 + i]); 
} 
void dfs(int x, int p) { 
    if (x && !check(x)) return ; 
    if (x == N) return (void)(ans += fac[p]); 
    dfs(x + 1, p); 
    int tmp[5], tot = 0; 
    for (int i = 1; i <= 1 << (N - x); i += 2) 
        if (a[(i - 1) * (1 << x) + 1] + (1 << x) !=
            a[i * (1 << x) + 1]) { 
            if (tot == 4) return ; 
            tmp[++tot] = i, tmp[++tot] = i + 1; 
        } 
    if (!tot) return ; 
    for (int i = 1; i <= tot; i++) 
        for (int j = i + 1; j <= tot; j++) { 
            Swap((1 << x) * (tmp[i] - 1) + 1, (1 << x) * (tmp[j] - 1) + 1, 1 << x); 
            dfs(x + 1, p + 1); 
            Swap((1 << x) * (tmp[i] - 1) + 1, (1 << x) * (tmp[j] - 1) + 1, 1 << x); 
        } 
} 
int main () {
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin);
#endif 
    fac[0] = 1; 
    for (int i = 1; i < 13; i++) fac[i] = fac[i - 1] * i; 
    scanf("%d", &N); 
    for (int i = 1; i <= 1 << N; i++) scanf("%d", a + i); 
    dfs(0, 0); 
    printf("%lld\n", ans); 
    return 0; 
} 
posted @ 2019-10-30 16:34  heyujun  阅读(...)  评论(... 编辑 收藏