Codeforces 453B Little Pony and Harmony Chest(状压)

题目链接:Codeforces 453B Little Pony and Harmony Chest

题目大意:给定一个序列a, 求一序列b,要求∑|ai?bi|最小。并且b中任意两数的最大公约束为1.

解题思路:因为b中不可能含有相同的因子,所以每个素数只能使用1次。又因为说ai最大为30,所以素数只需要考虑到57即可。因为即使对于30而言,59和1的代价是一样的。

所以有dp[i][j]表示的是到第i个数,使用过的素数j。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>

using namespace std;

const int maxn = 105;
const int sign[maxn] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
const int INF = 0x3f3f3f3f;
const int sn = 1<<16;

int N, num[maxn], s[maxn];
int dp[maxn][sn+5], rec[maxn][sn+5];

inline int getstate (int a) {
    int u = 0;
    for (int i = 0; i < 16; i++) {
        while (a % sign[i] == 0) {
            a /= sign[i];
            u |= (1<<i);
        }
    }
    return u;
}

inline void put_ans (int d, int S) {
    if (d == 0)
        return;

    int u = rec[d][S];
    put_ans(d-1, S^s[u]);
    num[d] = u;
}

void solve () {
    memset(rec, -1, sizeof(rec));
    rec[0][0] = 0;

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < sn; j++) {
            if (rec[i][j] == -1)
                continue;

            for (int k = 1; k < 60; k++) {
                if (j&s[k])
                    continue;

                int v = j|s[k];
                if (rec[i+1][v] == -1 || dp[i][j] + abs(k-num[i+1]) < dp[i+1][v]) {
                    rec[i+1][v] = k;
                    dp[i+1][v] = dp[i][j] + abs(k-num[i+1]);
                }
            }
        }
    }

    int ans = INF, id;
    for (int i = 0; i < sn; i++) {
        if (dp[N][i] < ans && rec[N][i] != -1) {
            ans = dp[N][i];
            id = i;
        }
    }

    put_ans(N, id);
    for (int i = 1; i < N; i++)
        printf("%d ", num[i]);
    printf("%d\n", num[N]);

}

int main () {
    for (int i = 1; i < 60; i++)
        s[i] = getstate(i);

    scanf("%d", &N);
    for (int i = 1; i <= N; i++)
        scanf("%d", &num[i]);

    solve();
    return 0;
}

Codeforces 453B Little Pony and Harmony Chest(状压),布布扣,bubuko.com

时间: 2024-10-31 11:06:24

Codeforces 453B Little Pony and Harmony Chest(状压)的相关文章

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 <<

codeforces 453 B Little Pony and Harmony Chest (状压dp)

题目大意: 需要你构造一个b数组.使得b数组中的所有元素互质. 而且使得b数组与a数组中的每个对应下标元素的差值和最小. 思路分析: 考虑到 a中所有元素都是 0 - 30. 所以b中的元素也只可能在 0 - 59. 因为如果b 选择60的话,结果和1是一样的,而且b序列中 1 可以重复出现很多次. 因为gcd (1,x) = 1.. 所以们首先把2 - 59中的所有素数处理出来,只有17个. 然后状压这些素数因子. dp[i] [s] [0] 表示 递推到第 i 个位置 达到素数因子为s的状态

Codeforces Round #259 (Div. 2) D. Little Pony and Harmony Chest 状压DP

D. Little Pony and Harmony Chest Princess Twilight went to Celestia and Luna's old castle to research the chest from the Elements of Harmony. A sequence of positive integers bi is harmony if and only if for every two elements of the sequence their gr

Codeforces 453B Little Pony and Harmony Chest:状压dp【记录转移路径】

题目链接:http://codeforces.com/problemset/problem/453/B 题意: 给你一个长度为n的数列a,让你构造一个长度为n的数列b. 在保证b中任意两数gcd都为1的情况下,使得 ∑|a[i]-b[i]|最小. 让你输出构造的数列b. (1<=n<=100, 1<=a[i]<=30) 题解: 因为1<=a[i]<=30,所以有1<=b[i]<=60,此时才有可能最优. 因为b中任意两数gcd为1,所以对于一个质因子p[i]

Codeforces 454D - Little Pony and Harmony Chest

454D - Little Pony and Harmony Chest 思路: 状压dp,由于1的时候肯定满足题意,而ai最大是30,所以只要大于等于59都可以用1替换,所以答案在1到59之间 然后筛出1到58之间的质数,只有16个,把1到58的数的状态由这16个质数表示,如果整除这个质数则二进制中这一位为1,否则则为0 状态:dp[i][j]表示到第i个数为止选取的数的状态为j的最小差和 初始状态:dp[0][0]=0 状态转移: dp[i+1][j|sta[k]]=min(dp[i+1][

Codeforces Round #259 (Div. 2)-D. Little Pony and Harmony Chest

题目范围给的很小,所以有状压的方向. 我们是构造出一个数列,且数列中每两个数的最大公约数为1; 给的A[I]<=30,这是一个突破点. 可以发现B[I]中的数不会很大,要不然就不满足,所以B[I]<=60左右.构造DP方程DP[I][J]=MIN(DP[I][J],DP[I][J^C[K]]+abs(a[i]-k)); K为我们假设把这个数填进数组中的数.同时开相同空间记录位置,方便输出结果.. #include<iostream> #include<stdio.h>

Codeforces Round #259 (Div. 1)——Little Pony and Harmony Chest

题目连接 题意: 给n个整数ai,求一个序列bi,使得b序列中任意两个数互质,而且sigma(abs(ai - bi))最小,输出任意一个b序列即可 (1?≤?n?≤?100)  (1?≤?ai?≤?30) 分析: 首先明确一点,题目没有限制b的范围....为此wa了好多次,不过可以推断出来,b肯定小于等于60 任意两个数互质,也就是说,对于新加入的一个bi,如果知道了之前所有数的质因子,那么当前数只要没有这个质因子就是一种满足的情况.而60以内的质数不到20个,所以直接状压DP即可.DP[i]

Little Pony and Harmony Chest CF4538 (状态压缩dp)

经典状态压缩dp #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #define min(x,y) (x>y?y:x) using namespace std; int factor[30],all,n,a[105],b[105][1<<17],pre[105][1<<17],s1,s0,f[105][1<<17]

codeforces 453B B. Little Pony and Harmony Chest(dp+数论)

题目链接: codeforces 453B 题目大意: 给出一个序列a,求取一个序列b,b序列的数两两互质,问能够导致∑|ai?bi|最小的方案 题目分析: 定义状态dp[i][j]表示前i个数达到j状态的最小的结果,j状态表示已经被用过的质数. 因为当一个a的数据范围不超过30,所以如果某个数超过60,那么选择1一定比它更优,所以我们能够用到的数的质因子也一定不会超过60,也才17个,所以我们只需要每次枚举数,然后通过之前的状态进行转移即可. 具体转移过程见代码. 为了得到方案,我们记录了pr