CF 453B Little Pony and Harmony Chest 解題報告(狀態壓縮DP)

B. 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 containsn 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.

Sample test(s)
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 

    解題報告: 上次CF的題,比賽時沒有想到。要求是將給定的n個數的序列變換成一個兩兩互質的序列,且每個數改動的和最小。

    直接狀態壓縮,記錄使用了哪些素數,達到的最小的改動和。因爲給定的ai<=30,那麼改動最大不超過58,30改成59和改成1得到的結果是一樣的。

    每次嘗試將當前數字改成1到58,最後取最小值即可。代碼如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
using namespace std;
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define bit(n) (1LL<<(n))
typedef long long LL;
typedef unsigned long long ULL;
const LL inf=1e15;
void work();
int main()
{
#ifdef ACM
    freopen("in.txt", "r", stdin);
#endif // ACM
    work();
}

/***************************************************/

int h[60];
int pri[18];
int tot;

int dp[105][bit(16)];
int ss[105][bit(16)];

void calPrime()
{
    fff(i, 2, 58) if(h[i] == 0)
    {
        pri[tot] = i;
        h[i] ^= bit(tot);
        for(int j=i+i;j<=58;j+=i)
            h[j] ^= bit(tot);

        tot++;
    }
}

void work()
{
    calPrime();

    int n;
    while(scanf("%d", &n) == 1)
    {
        memset(dp, 0x1f, sizeof(dp));
        dp[0][0] = 0;

        ff(i, n)
        {
            int cur;
            scanf("%d", &cur);

            ff(st, bit(tot)) if(dp[i][st] < 3000)
            {
                fff(j, 1, 58) if((st & h[j]) == 0 && dp[i+1][st ^ h[j]] > dp[i][st] + abs(cur - j))
                {
                    dp[i+1][st ^ h[j]] = dp[i][st] + abs(cur - j);
                    ss[i+1][st ^ h[j]] = j;
                }
            }
        }

        int mi = *min_element(dp[n], dp[n]+bit(tot));

        vector<int> ans;
        ff(st, bit(tot)) if(mi == dp[n][st])
        {
            int state = st;
            dff(i, n, 1)
            {
                ans.push_back(ss[i][state]);
                state = state ^ h[ss[i][state]];
            }
            break;
        }

        if(n) printf("%d", ans[n-1]);
        dff(i, n-2, 0) printf(" %d", ans[i]);
        puts("");
    }
}
發佈了227 篇原創文章 · 獲贊 13 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章