Problem
Little Pony and Harmony Chest
T i m e l i m i t : 4000 m s \mathrm{Time\;limit:\;4000\;ms} T i m e l i m i t : 4 0 0 0 m s
M e m o r y l i m i t : 262144 K B \mathrm{Memory\;limit:\;262144\;KB} M e m o r y l i m i t : 2 6 2 1 4 4 K B
Description
Princess Twilight went to Celestia and Luna’s old castle to research the chest from the Elements of Harmony.
![](https://odzkskevi.qnssl.com/27446e1e5b6e7b1f3e93c237f646aae1?v=1512139280)
A sequence of positive integers b i b_i b i is harmony if and only if for every two elements of the sequence their greatest common divisor equals 1 1 1 . According to an ancient book, the key of the chest is a harmony sequence bi which minimizes the following expression:
∑ i = 1 n ∣ a i − b i ∣ \sum_{i=1}^{n}{|a_i-b_i|}
i = 1 ∑ n ∣ a i − b i ∣
You are given sequence a i a_i a i , help Princess Twilight to find the key.
The first line contains an integer n ( 1 ≤ n ≤ 100 ) n (1\le n\le 100) n ( 1 ≤ n ≤ 1 0 0 ) — the number of elements of the sequences a a a and b b b . The next line contains n n n integers a 1 , a 2 , ⋯ , a n ( 1 ≤ a i ≤ 30 ) a_1,a_2,\cdots,a_n (1\le a_i\le 30) a 1 , a 2 , ⋯ , a n ( 1 ≤ a i ≤ 3 0 ) .
Output
Output the key — sequence bi that minimizes the sum described above. If there are multiple optimal sequences, you can output any of them.
Example
Input #1
Output #1
Input #2
Output #2
标签:状压DP
Translation
题目大意:给出一个n n n 个元素的序列a a a ,要求找一个n n n 个元素的序列b b b ,使得b b b 中的数两两互质,且要最小化∣ a i − b i ∣ |a_i-b_i| ∣ a i − b i ∣ 之和。
Solution
对于互质的条件,发现其相当于每个质因子只能用一次(1 1 1 可以用无限次)。发现a i a_i a i 的范围只有30 30 3 0 ,而如果b i ≥ 2 × a i b_i\ge 2\times a_i b i ≥ 2 × a i ,则取1 1 1 会更优。因此质因子只可能在1 ∼ 60 1\sim 60 1 ∼ 6 0 之间,只有17 17 1 7 个,可以状压。
预处理1 ∼ 60 1\sim 60 1 ∼ 6 0 中所有数占用的质因子状态,存在数组s t a [ ] sta[] s t a [ ] 中。
f [ i ] [ j ] f[i][j] f [ i ] [ j ] 表示当前选到第i i i 个数,质因子的选择状态为j j j 的最大答案。
对于一个数k k k ,若 j & s t a [ k ] ≠ 0 j\&sta[k]\ne 0 j & s t a [ k ] = 0 ,则不能选。
否则有 f [ i + 1 ] [ j ∣ s t a [ k ] ] = m a x ( f [ i + 1 ] [ j ∣ s t a [ k ] ] , f [ i ] [ j ] + a b s ( a [ i + 1 ] − k ) ) f[i+1][j|sta[k]] = max(f[i+1][j|sta[k]], f[i][j]+abs(a[i+1]-k)) f [ i + 1 ] [ j ∣ s t a [ k ] ] = m a x ( f [ i + 1 ] [ j ∣ s t a [ k ] ] , f [ i ] [ j ] + a b s ( a [ i + 1 ] − k ) )
对于输出方案,存下转移到f [ i ] [ j ] f[i][j] f [ i ] [ j ] 的状态g [ i ] [ j ] g[i][j] g [ i ] [ j ] 和选的数h [ i ] [ j ] h[i][j] h [ i ] [ j ] ,递归输出即可。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <bits/stdc++.h> #define SZ 17 #define MX 60 #define MAX_N 100 #define INF 0x3f3f3f3f using namespace std;int pri[SZ] = {2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 , 41 , 43 , 47 , 53 , 59 };int n, a[MAX_N+5 ], f[MAX_N+5 ][1 <<SZ], g[MAX_N+5 ][1 <<SZ], h[MAX_N+5 ][1 <<SZ], sta[MX];void init () { for (int i = 0 ; i <= n; i++) for (int j = 0 ; j < (1 <<SZ); j++) f[i][j] = INF, g[i][j] = h[i][j] = 0 ; f[0 ][0 ] = 0 ; memset (sta, 0 , sizeof sta); } void prt (int i, int j) {if (!i) return ; prt (i-1 , g[i][j]), printf ("%d " , h[i][j]);}int main () { while (~scanf ("%d" , &n)) { init (); for (int i = 1 ; i <= n; i++) scanf ("%d" , a+i); for (int i = 2 ; i < MX; i++) for (int j = 0 ; j < SZ; j++) if (i%pri[j] == 0 ) sta[i] |= (1 <<j); for (int i = 0 ; i < n; i++) for (int j = 0 ; j < (1 <<SZ); j++) { if (f[i][j] == INF) continue ; for (int k = 1 ; k < MX; k++) { if (j&sta[k]) continue ; if (f[i+1 ][j|sta[k]] > f[i][j]+abs (a[i+1 ]-k)) f[i+1 ][j|sta[k]] = f[i][j]+abs (a[i+1 ]-k), g[i+1 ][j|sta[k]] = j, h[i+1 ][j|sta[k]] = k; } } int pos = -1 , ans = INF; for (int i = 0 ; i < (1 <<SZ); i++) if (f[n][i] < ans) pos = i, ans = f[n][i]; prt (n, pos), puts ("" ); } return 0 ; }