题目链接: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 1105B - Zuhair and Strings 测试点37个(全)
Codeforces - 1107B. Digital root & 1107C. Brutality(规律 & 贪心)Codeforces - 1107B.
Codeforces 题库 101-200 共~500题 codeforces.com版权所有。 程序可提交至该网站评测。
Codeforces 题库 001-100 共~500题 codeforces.com版权所有。 程序可提交至该网站评测。
codeforces编程网站预测分数插件
codeforces每日一题。 题意: 给出一个数组,让你挑选出能组成任意pair差值为2的幂的序列,并且使这个序列长度尽可能大。 思路: 针对于挑选出来的序列,任意pair对的差值为2的幂数。 假设有多个pair对,设dis(a,b)=2...
暴枚最长桌脚的长度$l$,然后长度比$l$长的桌脚全部都要砍掉长度比$l$短的桌脚选择代价前$k$小的砍掉用线段树维护;示例程序 :typedef long l
使用于Google Chrome的Codeforces Enhancer 1.1.2插件安装包。 版本:codeforces enhancer 1.1.2 使用浏览器:Google Chrome
Codeforces 185A - Plant 全测试点49个
codeforces 19 E Fairy 一道比较难的题目的解题报告 推荐阅读
题目大意:给出一个由 n 个点组成的树,现在可以询问 n/2 次(向下取整)LCA,确定根节点是哪个节点 题目分析:因为最多只能求 n/2 次lca,每次需要两个节点作为参数,也就是说每个点我们至多遍历一遍,读完题后没什么...
Codeforces global round 10 codes
Codeforces round 678 division 2 codes
题意: 给出 nnn 个点,n−1n-1n−1 条边,最多询问 n2\frac{n}{2}2n 次,每次询问 u,vu,vu,v,会给出 uvuvuv的最近公共祖先,求树的根。 ...操作就是一个删除叶子节点的过程。 AC代码: const int N = 1010;...
Some of the Codeforces problems codes
如果a嘲讽b,b嘲讽c,那么(a,b,c)是一个三元组 问每次操作之后一共有多少对三元组 数据范围:n,m<=1e5,q<=1e5 三元组图例(未修改工资时): 图中三元组一共4组: 4->3->1 4->3->2 4->2->1 3->2->1 解法...
Codeforces Round #632 (Div. 2) C. Eugene and an array 题意: 求出一个数列中子区间满足 此区间的任意子区间之和 不为0的区间个数。 思路: 考虑用dp[x]dp[x]dp[x]记录前缀和为xxx的区间右端点。 那么这道题其实...
lucifer1004大佬的博客cf上分攻略故里大佬的githubcf思维题刷题数:44- (1421)codeforces 676 div2 A,B done
Codeforces round 678 D2_Codeforces_源码
题意: 在集合 S=1,2,⋯,nS={1,2,⋯,n}S=1,2,⋯,n 中,对于每个正整数 kkk ,找出一个大小为 kkk 的子集,使得该子集中两两间最大公因数的最大值最小,求这个最小值。 我们考虑如何构造两两间最大公因数的最大值最小...