Codeforces 454D Little Pony and Harmony Chest 状压DP

来源:互联网 发布:通达信源码论坛 编辑:程序博客网 时间:2024/06/06 20:50

点击打开链接

题意:n个数a[i],找到一组序列B,B中任意两个元素互质,最小值为?  n<=100,a[i]<=30

一定有解 并且b[i]不超过2*a[i]-1 若超过,b[i]用1来代替显然更优
b[i]范围被限制在60内,又要满足两两互质,用二进制记录前i个数中素因子出现的状态
设dp[i][s] 前i个数 素因子出现状态为s 则新添加的x要满足num[x]&s==0 否则有大于1的公约数  num[i]为i包含素因子的二进制状态
pre保存当前决策  复杂度为O(n*2^16*60)

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=2e2+20;const int M=1<<17;const int inf=0x3f;int a[N],b[N],n,pri[N],pn,num[N];//num[i] i°üº¬ËØÒò×ӵĶþ½øÖÆ״̬ int pre[N][M],dp[N][M];void init(){memset(num,0,sizeof(num));pn=0;int vis[110]={0};for(int i=2;i<60;i++){if(vis[i]==0){pri[pn++]=i;for(int j=i+i;j<60;j+=i)vis[j]=1;}}for(int i=2;i<60;i++){for(int j=0;j<pn;j++){if(i%pri[j]==0)num[i]|=1<<j;}}}int main(){init();while(cin>>n){for(int i=1;i<=n;i++)scanf("%d",&a[i]);memset(dp,0x3f,sizeof(dp));dp[0][0]=0;for(int i=1;i<=n;i++){for(int s=0;s<M;s++){for(int x=1;x<60;x++){//Ç°Ò»¸ö״̬ҪºÏ·¨ if(dp[i-1][s]==inf||(num[x]&s))continue;int res=dp[i-1][s]+abs(x-a[i]);if(dp[i][s|num[x]]>res){dp[i][s|num[x]]=res;pre[i][s|num[x]]=x;}}}}int pos,ans=2e8;for(int s=0;s<M;s++){if(ans>dp[n][s])ans=dp[n][s],pos=s;}for(int i=n;i>=1;i--){b[i]=pre[i][pos];pos=pos^num[b[i]];}for(int i=1;i<=n;i++)printf("%d%c",b[i],i==n?'\n':' ');}return 0;} 


阅读全文
0 0
原创粉丝点击