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

链接:

http://codeforces.com/contest/454/problem/D

题意:

给你一个a数组,求一个b数组,b中每两个数互质,并且最小。

题解:

状压DP,因为a<30,所以b中最大不会超过60,超过60就可以用1代替,想想59也是不需要的,所以除了1就剩下16个素数

状态压缩一下就可以,dp[i][j]表示到第i个数为止,已经用了哪些素数。代码改了好久,所以写的比较丑0.0

代码:

31 const int SN = 1 << 16;
32 int n;
33 int a[MAXN];
34 int dp[MAXN][SN + 7];
35 int s[60];
36 PII route[MAXN][SN + 7];
37 
38 int prime[20] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53 };
39 
40 inline int getstate(int a) {
41     int u = 0;
42     for (int i = 0; i < 16; i++) {
43         while (a % prime[i] == 0) {
44             a /= prime[i];
45             u |= (1 << i);
46         }
47     }
48     return u;
49 }
50 
51 void print(int last, int id) {
52     if (id == 1) {
53         cout << route[id][last].second;
54         return;
55     }
56     print(route[id][last].first, id - 1);
57     cout << ' ' << route[id][last].second;
58 }
59 
60 int main() {
61     ios::sync_with_stdio(false), cin.tie(0);
62     rep(i, 1, 60) s[i] = getstate(i);
63     cin >> n;
64     memset(dp, 0x3f, sizeof(dp));
65     dp[0][0] = 0;
66     rep(i, 1, n + 1) cin >> a[i];
67     rep(i, 1, n + 1) rep(j, 0, SN) rep(k, 0, 60) if ((j&s[k]) == 0)
68         if (dp[i][j | s[k]] > dp[i - 1][j] + abs(k - a[i])) {
69             dp[i][j | s[k]] = dp[i - 1][j] + abs(k - a[i]);
70             route[i][j | s[k]].first = j;
71             route[i][j | s[k]].second = k;
72         }
73     int ans = INF;
74     int last;
75     rep(j, 0, (1 << 16)) if (ans > dp[n][j]) {
76         ans = dp[n][j];
77         last = j;
78     }
79     print(last, n);
80     cout << endl;
81     return 0;
82 }

 

posted @ 2017-08-04 21:06  Flowersea  阅读(149)  评论(0编辑  收藏  举报