zoukankan      html  css  js  c++  java
  • [HEOI2015]定价(贪心+数学)

    传送门

    题意:给定区间[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
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    Bugku cookie欺骗
    Bugku 速度要快
    bugku 秋名山老司机
    关于进程三态(运行态、就绪态、阻塞态)的一些易混知识点
    (转)解决ubuntu下拼音输入法出错的问题
    Codeforces Round #402 (Div. 2)
    (转)codeblocks 使用研究
    (原+转)怎么解决ubuntu挂起后无法唤醒的问题(还是没解决!!求助!!)
    关于codeblocks插件(持续更新)
    自定义gvim配色方案qiucz.vim的源码
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10331587.html
Copyright © 2011-2022 走看看