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

codeforces 251C C. Number Transformation(数论+dp)

时间:2015-09-03 15:23:57      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:codeforces   dp   数论   

题目链接:

codeforces 251C


题目大意:

给出两个数a,b,k有两种操作,a-=1,或者a-=a%x(2<=x<=k),问最少需要多少步操作能够使a变成b


题目分析:

  • 首先我们考虑数据范围小的怎么做,dp[i]ai
  • {dp[i?1]=min(dp[i?1],dp[i]+1)dp[i?i%x]=min{(dp[i?i%x],dp[i]+1)|2xk}
  • 那么我们考虑题目给出的数据范围好大,直接做肯定超时,那么考虑每步操作只有a-=1和a-=a%x,那么我们考虑每次决策如果不选1的话,那么可能会更快的到达,但是如果所有的x都会被整除,那么选择1反而会得到最优解,所有的x都被整除,那么此时的数一定是所有x的lcm的倍数。
    {a=p?lcm+ba=p1?x1+b1?a=p?lcm+p3?x1+b1?a?b1=p?lcm+p3?x1?a?b1=p?lcm+q ( q=p3?x1)?a?b1=p?lcm+p4?x2+b2?a?b1?b2=p?lcm+p4?x2?a?i=1nbi=p?lcm+pn?xn

    所以每个lcm都是可达的,且一定要到达的,因为通过如上操作是不能跳过某一个lcm的倍数的,所以我们利用lcm分块,然后只需要根据性质,对相同性质的块操作只做一次就可以了。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 400007

using namespace std;

typedef long long LL;
LL a,b,dp[MAX];
int k;

LL gcd ( LL a , LL b )
{
    return b==0?a:gcd(b,a%b);
}

LL solve ( LL a , LL b )
{
    memset ( dp, 0x3f , sizeof ( dp ) );
    dp[a] = 0;
    for ( int i = a ; i > b ; i-- )
    {
        dp[i-1] = min( dp[i]+1 , dp[i-1] );
        for ( int j = 2 ; j <= k ; j++ )
            dp[i-i%j] = min ( dp[i-i%j] , dp[i]+1 );
    }
    return dp[b];
}

int main ( )
{
    while ( ~scanf ( "%lld%lld%d" , &a , &b , &k ) )
    {
        LL lcm = 2;
        for ( int i = 3; i <= k ; i++ )
        {
            int d = gcd ( i , lcm );
            lcm *= i;
            lcm /= d;
        }
        LL ans;
        if ( a/lcm == b/lcm )
            ans = solve ( a%lcm , b%lcm );
        else 
            ans = solve ( a%lcm , 0 ) + (a/lcm-b/lcm-1)*solve ( lcm , 0 ) + solve ( lcm , b%lcm );
        printf ( "%lld\n" , ans );
    }
}

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

codeforces 251C C. Number Transformation(数论+dp)

标签:codeforces   dp   数论   

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

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