题解:CF453B Little Pony and Harmony Chest
题目分析
本题要求构造一个长度为
- 序列中任意两个元素互质
- 最小化
\sum_{i=1}^{n} |a_i - b_i|
因为
别的证明,大佬们的题解不难理解,这里主要备忘一下转移方程。
从别的大佬那里可以知道
以及转移方程:
为什么
对于每一个质因数分解出来使用状态为
那么顺序来看,如果当前质数使用情况为
然后对于当前
当然,加上的
转移方程就只有这些,但题目中的输出还有点麻烦。
实现
针对输出,新增一个
#include<bits/stdc++.h>
using namespace std;
#define N 105
int n,ans,cnt;
int a[N],vis[N],c[N],maskk[N],dp[105][1<<17],pre[105][1<<17];
int mask(int k){
int an=0;
for(int i=1;i<=cnt;i++){
if(k%a[i]==0){
k/=a[i];
an|=(1<<(i-1));
}
if(k==0) break ;
}
return an;
}
void write(int nn,int ll){
if(nn==0) return ;
write(nn-1,ll^maskk[pre[nn][ll]]);//ll一定是包含maskk的
cout<<pre[nn][ll]<<" ";
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>c[i];
}
for(int i=2;i<=58;i++){
if(!vis[i]) a[++cnt]=i;
for(int j=1;j<=cnt&&a[j]*i<=58;j++){
vis[a[j]*i]=1;
if(i%a[j]==0) break;
}
}
for(int i=1;i<=58;i++) maskk[i]=mask(i);
memset(dp,0x3f,sizeof(dp));
//dp[i][mask],考虑前 i个元素,已使用的质因数集合为 mask时的最小差和
dp[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=(1<<16)-1;j++){
for(int k=1;k<=58;k++){
int mak=maskk[k];
if((j|mak)!=j) continue ; //如果j不完全包括mak
//j^mak把max从j中消除
if(dp[i][j]>dp[i-1][j^mak]+abs(k-c[i])){
dp[i][j]=dp[i-1][j^mak]+abs(k-c[i]);
pre[i][j]=k;
}
}
}
}
ans=0x3f3f3f;
int ll=0;
for(int i=0;i<=(1<<16)-1;i++){
if(ans>dp[n][i]){
ans=dp[n][i];
ll=i;
}
}
write(n,ll);
return 0;
}