首页 > 代码库 > Codeforces 453B Little Pony and Harmony Chest 状压dp

Codeforces 453B Little Pony and Harmony Chest 状压dp

题目链接:点击打开链接

b的数字最多只能达到59,因为选>=60 不如选1

所以状压一下前面出现过的素数即可,在59内的素数很少

然后暴力转移。。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string.h>
const int Inf = (int)(1e9);
const int S = 1 << 17;
const int N = 100 + 2;
bool isPrime(int x) {
    if (x < 2)
        return false;
    for (int i = 2; i * i <= x; ++i)
        if (x % i == 0)
            return false;
    return true;
}
int hehehehe;
int son[60], a[N], out[N];
std::vector<int>prime;
int d[N][S], pre[N][S];

void dfs(int i, int j) {
    if(i == 0)
        return ;
    else {
        out[i] = pre[i][j];
        dfs(i - 1, j ^ son[pre[i][j]]);
    }
}

int main() {
    for (int i = 2; i < 60; ++i)
        if(isPrime(i))
            prime.push_back(i);
    for (int i = 1; i < 60; ++i)
        for (int j = 0; j < prime.size(); ++j)
            if (i % prime[j] == 0)
                son[i] |= 1 << j;

    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        scanf("%d", &a[i]);

    memset(pre, -1, sizeof pre);
    for (int i = 0; i <= n; ++i)
        for (int j = 0; j < S; ++j)
            d[i][j] = Inf;
    d[0][0] = 0;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < S; ++j)
            if (d[i][j] != Inf) {
                for (int k = 1; k < 60; ++k)
                if ((son[k] & j) == 0) {
                    if (d[i + 1][son[k] | j] >= d[i][j] + abs(a[i] - k)) {
                        d[i + 1][son[k] | j] = d[i][j] + abs(a[i] - k);
                        pre[i + 1][son[k] | j] = k;
                    }
                }
            }

    int ansv = Inf, ansj;
    for (int j = 0; j < S; ++j)
    if (d[n][j] <= ansv) {
        ansv = d[n][j];
        ansj = j;
    }
    dfs(n, ansj);
    for (int i = 1; i <= n; ++i) {
        if(i > 1)
            putchar(' ');
        printf("%d", out[i]);
    }
    return 0;
}