[HEOI2015] 定价

题目链接:https://www.luogu.org/problemnew/show/P4109

【题目描述】
在市场上有很多商品的定价类似于 999 元、 4999 元、 8999 元这样。它们和 1000 元、 5000 元和 9000 元并没有什么本质区别,但是在心理学上会让人感觉便宜很多,因此也是商家常用的价格策略。不过在你看来,这种价格十分荒谬。于是你如此计算一个价格 p p 为正整数)的荒谬程度:

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

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

  3. p 的长度为 a ,如果此时 p 的最后一位是 5 ,则荒谬程度为 2 a 1 ;否则为 2 a

例如, 850 的荒谬程度为 3 ,而 880 则为 4 9999 的荒谬程度为 8

现在,你要出售一样闲置物品,你能接受的定价在 [ L , R ] 范围内,你想要给出一个荒谬度最低的价格。

【输入格式】
输入文件的第一行包含一个正整数 T ,表示测试数据的数目。

每个测试数据一行,包含两个空格分隔的正整数 L , R ,表示定价的区间。

【输出格式】
对于每个测试数据,在单独的一行内输出结果。如果荒谬度最低的价格不唯一,输出最小的那个。

【输入样例】

3
998 1002
998 2002
4000 6000

【输出样例】

1000
1000
5000

【说明】
对于 20 % 的数据, L , R 2000
对于 100 % 的数据, T 100 1 L R 10 9

【题解】
这题的样例中,答案末尾有许多 0 。这启示我们观察 0 的个数。

枚举定价有多少个 0 后,可以得到去掉 0 后的 p 值可能取到的左右端点 l e f t , r i g h t

因为 p 的长度差 1 ,荒谬程度至少差 2 ,比末尾是 5 的差 1 更重要。所以要让 p 的长度最小。又因为输出要求的也是取最小的最优解,所以直接检验左端点 l e f t 即可。

对于末尾是 5 的情况,同理可得,也应该取最小的可取的数。也就是直接left++直到末尾是 5 为止,再检验一次即可。

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t,l,r,nlen=1e9,num;
void check(int x){ /* 检验x是否比最优解更好,是则存在num中 */
    int oldx=x; /* 将x备份 */
    int last=0,len=0;
    while (x%10==0) x/=10; /* 进行第2步:去掉末尾的0 */
    last=x%10;
    while (x) len++,x/=10;
    len*=2;
    if (last==5) len--; /* 进行第3步:计算长度 */
    if (len<nlen){ /* 更新最优解 */
        nlen=len;
        num=oldx;
    }
}
int solve(){
    for (int zero=0;zero<=9;zero++){ /* 枚举定价有多少个0 */
        int left=ceil(l/(double)pow(10,zero));
        int right=floor(r/(double)pow(10,zero));
         /* left,right分别为去掉0后的值可能取到的左右端点 */
        if (right<left) continue; /* 不存在满足条件的数 */
        if (left%10==0) left++; /* 确保正好是这么多0 */
        check(left*pow(10,zero)); /* (1)末尾不为5的情况 */
        while (left%10!=5) left++;
        if (right<left) continue; /* 不存在满足条件且末尾为5的数 */
        check(left*pow(10,zero)); /* (2)末尾为5的情况 */
    }
    return num;
}
int main(){
    // freopen("absurd.in","r",stdin);
    // freopen("absurd.out","w",stdout);
    cin>>t;
    for (int i=1;i<=t;i++){
        cin>>l>>r;
        nlen=1e9,num=0; /* 初始化,nlen为荒谬程度,num为最优解 */
        cout<<solve()<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/orzzmh/article/details/80944441