码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces 453B B. Little Pony and Harmony Chest(dp+数论)

时间:2015-10-03 15:43:39      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:codeforces   dp   数论   

题目链接:

codeforces 453B


题目大意:

给出一个序列a,求取一个序列b,b序列的数两两互质,问能够导致|ai?bi|最小的方案


题目分析:

  • 定义状态dp[i][j]表示前i个数达到j状态的最小的结果,j状态表示已经被用过的质数。
  • 因为当一个a的数据范围不超过30,所以如果某个数超过60,那么选择1一定比它更优,所以我们能够用到的数的质因子也一定不会超过60,也才17个,所以我们只需要每次枚举数,然后通过之前的状态进行转移即可。
  • 具体转移过程见代码。
  • 为了得到方案,我们记录了pre[i][j]代表前i个数达到状态j得到最大值的前一个状态,num[i][j]表示前i个数达到状态j得到最大值的最后选取的数字。

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#define MAX 107

using namespace std;

int n,a[MAX];
int dp[107][1<<17];
int pre[107][1<<17];
int num[107][1<<17];
int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,39,41,43,47,53};
int state[60];

void print ( int i ,int u )
{
    if ( i == 1 ) 
    {
        printf ( "%d " , num[i][u] );
        return;
    }
    print ( i-1 , pre[i][u] );
    printf ( "%d " , num[i][u] );
}

int main ( )
{
    while ( ~scanf ( "%d" , &n ) )
    {
        for ( int i = 1 ; i <= n ; i++ )
            scanf ( "%d" , &a[i] );
        memset ( dp , 0x3f , sizeof ( dp ) );
        int INF = dp[0][0];
        dp[0][0] = 0; 
        memset ( state , 0 , sizeof ( state ) );
        for ( int i = 2 ; i < 60 ; i ++ )
            for ( int j = 0; j < 17 ; j++ )
                if ( i%prime[j] == 0 )
                    state[i] |= (1<<j);
        int total = 1<<17;
        for ( int i = 0 ; i < n ; i++ )
            for ( int j = 0 ; j < total ; j++ )
            {
                if ( dp[i][j] == INF ) continue;
                for ( int k = 1 ; k < 59 ; k++ )
                {
                    if ( state[k]&j ) continue;
                    int x = state[k]|j;
                    if ( dp[i+1][x] > dp[i][j] + abs ( a[i+1] - k ) )
                    {
                        dp[i+1][x] = dp[i][j] + abs ( a[i+1] - k );
                        pre[i+1][x] = j;
                        num[i+1][x] = k;
                    }
                }
            }
        int ans = INF,loc = -1;
        for ( int i = 0 ; i < total ; i++ )
            if ( ans > dp[n][i] )
            {
                ans = dp[n][i];
                loc = i;
            }
        print ( n ,  loc );
        puts ("");
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

codeforces 453B B. Little Pony and Harmony Chest(dp+数论)

标签:codeforces   dp   数论   

原文地址:http://blog.csdn.net/qq_24451605/article/details/48878237

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!