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的状态下,第 i 个位置放的数。

dp[i] [s] [1] 表示。。。。。。。。。。。。。。。。。。。。。的最小值。

dp[i] [s] [2] 表示。。。。。。。。。。。。。。。。。。。。。的前驱,方便输出方案。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

int prime[20];
bool isprime(int x)
{
    for(int i=2;i<x;i++)
        if(x%i==0)return false;
    return true;
}

int dp[105][1<<17][3];
int n;
int a[105];
int Abs(int x)
{
    return x>0?x:-x;
}
void print(int dep,int x)
{
    if(dep==0)return;
    print(dep-1,dp[dep][x][0]);
    printf("%d ",dp[dep][x][2]);
}
int main()
{
    int cnt=0;
    for(int i=2;i<=59;i++)
        if(isprime(i))prime[cnt++]=i;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);

    int s;
    memset(dp,0x3f,sizeof dp);

    for(int i=0;i<(1<<17);i++)dp[0][i][0]=dp[0][i][1]=dp[0][i][2] = 0;

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=59;j++)
        {
            s=0;
            for(int k=0;k<cnt;k++)
            {
                if(j%prime[k]==0)
                    s|=(1<<k);
            }
            for(int st=1;st<(1<<17);st++)
            {
                if(!(st&s))
                {
                    if(dp[i-1][st][1]+Abs(a[i]-j)<dp[i][st|s][1])
                    {
                        dp[i][st|s][2]=j;
                        dp[i][st|s][1]=dp[i-1][st][1]+Abs(a[i]-j);
                        dp[i][st|s][0]=st;
                    }
                }
            }
        }
    }

    int ans=0x3f3f3f3f;
    int pos=0;
    for(int i=0;i<(1<<17);i++)
    {
        if(dp[n][i][1]<ans)
        {
            ans=dp[n][i][1];
            pos=i;
        }
    }
    return 0;
}

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

时间: 2024-10-01 22:46:21

codeforces 453 B 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 <<

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(状压)

题目链接: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 <cs

CodeForces 757D Felicity&#39;s Big Secret Revealed(状压DP)

题意:给定一个01串,一个有效的n切割定义如下:一个横杠代表一次切割,第一条横杠前面的01串不算,最后一条横杠后面的01串不算,将两个横杠中的01串转化成十进制数字,假设这些数字的最大值是MAX且这些数字囊括了1-MAX的所有数字,则称为一次有效切割.求2~n+1次有效切割的切法. 思路: 由于题目要求包含所有1-MAXN的数字,且n<=75,所以MAXN<=20.另dp[i][j]表示第i位前面有一个横杆且存在j这个状态,接着从第i位开始枚举到第j位为下一个横杆的位置,设这两段横杆之间的数字

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

【Codeforces】Gym 101173B Bipartite Blanket 霍尔定理+状压DP

题意 给一张$n\times m$二分图,带点权,问有多少完美匹配子集满足权值和大于等于$t$ 这里有一个结论:对于二分图$\mathbb{A}$和$\mathbb{B}$集合,如果子集$A \in \mathbb{A},B \in \mathbb{B}$,且$A,B$分别是完美匹配的子集,那么$A \cup B$属于一个完美匹配 有了这个结论之后,考虑单侧,枚举子集$S$,利用霍尔定理判定$S$是否是完美匹配,并通过dp转移状态,记录下单侧所有满足条件的权值和,然后两侧一起考虑累加得到答案 时

【Codeforces】CF 165 E Compatible Numbers(状压dp)

题目 传送门:QWQ 分析 很难想到方向,但有方向了就很easy了. 我们如何减少不必要的计算? 如果我们知道了$ 100111 $的相容的数,$ 100101 $的相容数和他是完全一样的. 我们就靠着这个思想写一下就行了. 注意位运算优先级. 代码 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1<<22, INF=(1<<22)-1; 4 5 int dp[maxn], a[ma

Codeforces 744C Hongcow Buys a Deck of Cards 状压dp (看题解)

Hongcow Buys a Deck of Cards 啊啊啊, 为什么我连这种垃圾dp都写不出来.. 不是应该10分钟就该秒掉的题吗.. 从dp想到暴力然后gg, 没有想到把省下的红色开成一维. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair&

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>