CF Round 259 DD. Little Pony and Harmony Chest 状态压缩DP

题目链接http://codeforces.com/contest/454/problem/D

题目大意:给你n个数字a1~an,要你找n个数字b1~bn满足Σ|ai - bi|最小,并且b1~bn这n个数互质,输出这组数。1 ≤ ai ≤ 30 1 ≤ n ≤ 100

解题思路:n个数互质即说明他们之间的质因子不相同,而由于ai <= 30,所以可以将60以内的素数打表然后进行状态压缩,以每一位的值表示对应素数是否是一个数的质因子。

然后就是针对每个ai,决策----60以内选一个满足条件的数。设dp[i][j]:=前i个数使用的素数为j所示时所求和的最小值,那么转移方程:

dp[i][ij] = min(dp[i][j], dp[i - 1][j ^ (k的质因子状态)] + abs(a[i] - k))  1 <= k <= 60, k & j == 0

大体思路:

前16个素数(ai<= 30,所以59和1实际上是等价的)打表

对1~60的每个数计算对应状态,即 10110表示(从低位到高位)第1个素数不是其质因子,第二个,第三个素数是,第四个不是,第五个是。

初始化dp[0][i] = 0,循环求dp[i][j]并且记录路经

沿着路径查找压栈,最后输出。

代码:

 1 const int maxn = 1e2 + 5, maxm = (1 << 16) + 5;
 2 int n, a[maxn];
 3 int prifac[65], dp[maxn][maxm];
 4 struct node{
 5     int i, j, k;
 6 }pre[maxn][maxm];
 7 
 8 void solve(){
 9     int primes[20] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
10     int pribit[20];
11     for(int i = 0; i < 16; i++) pribit[i] = 1 << i;
12     for(int i = 1; i <= 60; i++) {
13         for(int j = 0; j < 16; j++){
14             if(i % primes[j] == 0) prifac[i] = prifac[i] | pribit[j];
15         }
16     }
17     
18     memset(dp, 0x3f, sizeof(dp));
19     memset(pre, 0, sizeof(pre));
20     for(int i = 0; i < maxm; i++) dp[0][i] = 0;
21     for(int i = 1; i <= n; i++){
22         for(int j = 0; j < (1 << 16); j++){
23             for(int kk = 1; kk <= 60; kk++){
24                 int k = prifac[kk];
25                 if((k & j) == 0 && dp[i - 1][j ^ k] + abs(kk - a[i]) < dp[i][j]){
26                     dp[i][j] = dp[i - 1][j ^ k] + abs(kk - a[i]);
27                     pre[i][j].i = i - 1; pre[i][j].j = j ^ k; pre[i][j].k = kk;
28                 }
29             }
30         }
31     }
32     int mi = n, mj = 0;
33     int tmans = inf;
34     for(int i = 0; i < (1 << 16); i++){
35         if(dp[n][i] < tmans) {
36             tmans = dp[n][i];
37             mj = i;
38         }
39     }
40     stack<int> s;
41     while(mi > 0){
42         s.push(pre[mi][mj].k);
43         int tmi = pre[mi][mj].i, tmj = pre[mi][mj].j;
44         mi = tmi; mj = tmj;
45     }
46     while(!s.empty()){
47         printf("%d", s.top());
48         s.pop();
49         if(s.empty()) printf("
");
50         else printf(" ");
51     }
52 }
53 int main(){
54     scanf("%d", &n);
55     for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
56     solve();
57     return 0;
58 }

题目:

D. Little Pony and Harmony Chest
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 greatest common divisor equals 1. According to an ancient book, the key of the chest is a harmony sequence bi which minimizes the following expression:

You are given sequence ai, help Princess Twilight to find the key.

Input

The first line contains an integer n (1 ≤ n ≤ 100) — the number of elements of the sequences a and b. The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 30).

Output

Output the key — sequence bi that minimizes the sum described above. If there are multiple optimal sequences, you can output any of them.

Examples
input
5
1 1 1 1 1
output
1 1 1 1 1 
input
5
1 6 4 2 8
output
1 5 3 1 8 

 

原文地址:https://www.cnblogs.com/bolderic/p/7358449.html