CF453B CF454D
Codeforces Round #259 (Div. 2) D
Codeforces Round #259 (Div. 1) B
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. Sample test(s)
Input
5 Output
1 1 1 1 1 Input
5 Output
1 5 3 1 8 |
题意:给出n个元素组成的a[i],求b[i],要求b[i]每两个元素互质(最大公约数为1),使各个i的abs(b[i]-a[i])的和最小。n<=100,a[i]<=30
题解:状压DP。
可以发现其实我们就用这么几个数,因为1是可以无限用的,最差我们就用1,a[i]=30的时候,距离1和59一样近,所以我们b[i]就从1~59里面选。
然后要互质,就是要两个数没有相同的约数,可以当做两个数不是同一个质数的倍数。这样我们把某个数的质因数标记上,另一个数的质因数要是和这个数的质因数有重合,就不行。
然后1~59之间,质数只有17个,可以用1<<17种状态表示已经用了哪些质数当因数。这样我们就能用超碉的状态压缩DP了。
f[i][j] 搞完第i个数,状态为j的最小消耗。初始化为INF,f[0][0]为0。
g[i][j] 记这个状态b[i]放的是什么数
pre[i][j] 记上个状态是什么
途中会多次用到某个数的质因数们,可以先算好st[]存1~59的质因数的状态。
若(st[l]&j)为真,说明j这个状态后面不能加l这个数了……
代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
#define ll long long
#define usll unsigned ll
#define mz(array) memset(array, 0, sizeof(array))
#define minf(array) memset(array, 0x3f, sizeof(array))
#define REP(i,n) for(i=0;i<(n);i++)
#define FOR(i,x,n) for(i=(x);i<=(n);i++)
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define WN(x) prllf("%d\n",x);
#define RE freopen("D.in","r",stdin)
#define WE freopen("1biao.out","w",stdout)
#define mp make_pair
#define pb push_back
const int maxj=<<;
const int inf=0x3f3f3f3f;
const int pr[]= {,,,,,,,,,,,,,,,,,},pn=;
int isp[]= {};
int f[][maxj];///f[i][j] 搞完第i个数,状态为j的最小消耗
int g[][maxj];///记这个状态b[i]放的是什么数
int pre[][maxj];///记上个状态是什么 int st[]; int n;
int a[];
int main() {
int i,j,k,l;
mz(isp);
REP(i,pn) isp[pr[i]]=;
for(k=; k<=; k++) {
st[k]=;
for(l=; pr[l]<=k; l++) {
if(k%pr[l]==) st[k]|=(<<l);
}
} scanf("%d",&n);
REP(i,n)scanf("%d",&a[i]);
mz(g);
mz(pre);
memset(f,0x3f,sizeof(f));
f[][]=;
for(i=; i<n; i++) {
for(j=; j<maxj; j++) {
if(f[i][j]!=inf) {
for(k=; k<=; k++) {
int x=st[k];
if(x&j)continue;
x=x|j;
int biu=f[i][j] + abs(k-a[i]);
if(biu<f[i+][x]) {
//printf("%d %d %d %x\n",i,j,k,x);
f[i+][x]=biu;
g[i+][x]=k;
pre[i+][x]=j;
}
}
}
}
}
l=;
for(j=; j<maxj; j++) {
if(f[n][j]<f[n][l])l=j;
}
vector<int>ans;
ans.clear();
for(i=n; i>; i--) {
ans.pb(g[i][l]);
l=pre[i][l];
}
j=ans.size();
printf("%d",ans[j-]);
for(i=j-; i>=; i--)
printf(" %d",ans[i]);
puts("");
return ;
}