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

[HEOI2015]定价

时间:2019-01-28 21:18:49      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:https   完全   break   朴素   贪心   个数   pow   测试数据   \n   

传送门

题意:给定区间[L,R]求出区间内荒谬程度最小的数

注意:有多组测试数据,且\(1≤L≤R≤10^9\).

如此计算一个正整数p的荒谬程度:

(1) 首先将p看做一个由数字组成的字符串(不带前导0).

(2) 然后,如果p的最后一个字符是0,就去掉它.重复这一过程,直到p的最后一个字符不是0.

(3) 记此时数字p的长度为len,如果p的最后一位是5,则荒谬程度为\(2*len-1\);否则为\(2*len\).

分析:我们最先想到的暴力肯定是枚举区间内的每一个数,然后计算它的荒谬程度,一一比较得出荒谬程度最小的数.但是这样肯定会超时.考虑如何美妙地优化这种暴力做法,即做到优雅的暴力.

举个例子,对于一个数20300,按照上述暴力做法,每次加1,会使其后的00变为01--->02--->03...反而使得其荒谬程度变大,所以完全没有必要这样做.

不如从这个数字的最低的非零位开始加起,即每次加\(10^{num}\)(num是这个数字末尾的零的个数),于是乎20300--->20400...--->21000...我们就是采取了这样一种贪心策略来优化最朴素的暴力,时间复杂度为O(数位\(*10*\)数位)

int main(){
    int T=read();
    while(T--){
        int l=read(),r=read(),minn=20,ans;
        while(l<=r){
            int l1=l,num=0;
            while(l1%10==0){l1/=10;num++;}
//num是当前枚举到的数字的末尾的零的个数
            int last=l1%10,len=0;
            while(l1){l1/=10;len++;}
//last是最低非零位上的数字
//len是从 最低非零位到最高位上 的数字个数
            int sum;
            if(last==5)sum=2*len-1;
            else sum=2*len;
//sum是荒谬程度
            if(sum<minn)minn=sum,ans=l;
//更新最小荒谬程度,更新答案
            if(sum==1)break;
//一个小小的优化:荒谬程度为1,肯定是最小的.
            l+=pow(10,num);
//枚举:每次自增10^num
        }
        printf("%d\n",ans);
    }
    return 0;
}

[HEOI2015]定价

标签:https   完全   break   朴素   贪心   个数   pow   测试数据   \n   

原文地址:https://www.cnblogs.com/PPXppx/p/10331587.html

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