Codeforces 453B Little Pony and Harmony Chest(状压)

题意:给一个a数组,求出一个数组b使得b数组和a数组的差值的绝对值最小,并且b数组里面的数字两两互质.
解析:
由于ai的范围<=30,所以>58的数字就可以被1取代,
考虑到b数组里面的数字两两互质,即质因子最多出现一次
所有质因子只有<=58的16个,状态压缩就比较明白了.

具体看代码注释:

#include<bits/stdc++.h>
using namespace  std;
#define ll long long
#define pb push_back
#define inf 2099999999
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i>=b;i--)
const int N=1e2+10;
const int all=1<<16;
int ar[N];
int vis[N][all+5];//表示状态是否到达过
int dp[N][all+5];//dp[i][j]表示第i个数字所到达的第j个状态
int s[N];//s[i]表示i这个数字所占有的质因子
int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
/**

*/
void dfs(int d,int S)
{
    if(d==0) return ;
    int u=vis[d][S];
    dfs(d-1,S^s[u]);//把S中对应的质因子去掉
    cout<<u<<' ';
}
int main()
{
    #ifdef LOCAL_DEFINE
        freopen("D://rush.txt", "r", stdin);
    #endif
    ios::sync_with_stdio(false),cin.tie(0);
    int n;
    for(int i=1;i<60;i++)
    {
        int a=i;
        for(int j=0;j<16;j++)
        {
            while(a%prime[j]==0)
            {
                a/=prime[j];
                s[i]|=(1<<j);
            }
        }
    }

    cin>>n;
    rep(i,1,n) cin>>ar[i];
    memset(vis,-1,sizeof vis);
    vis[0][0]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<all;j++)//在第i个数前的所有状态
        {
            if(vis[i-1][j]!=-1)//这个状态之前达到过
            {
                for(int k=1;k<60;k++)
                {
                    if((j&s[k])==0)//要选的这个数和已经存在的状态没有相同的质因子
                    //这个括号让我调试了一下午...
                    {
                        int y = j|s[k];//添加新的质因子
                        if(vis[i][y]==-1||dp[i-1][j]+abs(k-ar[i])<dp[i][y])
                        {
                            vis[i][y]=k;
                            dp[i][y]=dp[i-1][j]+abs(k-ar[i]);
                        }
                    }
                }
            }
        }
    }
    int ans=inf,id=0;
    for(int i=0;i<all;i++)
    {

        if(dp[n][i]<ans&&vis[n][i]!=-1)
        {
            ans=dp[n][i];
            id=i;
        }
    }
    dfs(n,id);
}

猜你喜欢

转载自blog.csdn.net/ffgcc/article/details/81045452