题目链接:https://www.luogu.org/problemnew/show/P4109
【题目描述】
在市场上有很多商品的定价类似于
元、
元、
元这样。它们和
元、
元和
元并没有什么本质区别,但是在心理学上会让人感觉便宜很多,因此也是商家常用的价格策略。不过在你看来,这种价格十分荒谬。于是你如此计算一个价格
(
为正整数)的荒谬程度:
首先将 看做一个由数字组成的字符串(不带前导 );
然后,如果 的最后一个字符是 ,就去掉它。重复这一过程,直到 的最后一个字符不是 ;
记 的长度为 ,如果此时 的最后一位是 ,则荒谬程度为 ;否则为 。
例如, 的荒谬程度为 ,而 则为 , 的荒谬程度为 。
现在,你要出售一样闲置物品,你能接受的定价在 范围内,你想要给出一个荒谬度最低的价格。
【输入格式】
输入文件的第一行包含一个正整数
,表示测试数据的数目。
每个测试数据一行,包含两个空格分隔的正整数 ,表示定价的区间。
【输出格式】
对于每个测试数据,在单独的一行内输出结果。如果荒谬度最低的价格不唯一,输出最小的那个。
【输入样例】
3
998 1002
998 2002
4000 6000
【输出样例】
1000
1000
5000
【说明】
对于
的数据,
。
对于
的数据,
,
。
【题解】
这题的样例中,答案末尾有许多
。这启示我们观察
的个数。
枚举定价有多少个 后,可以得到去掉 后的 值可能取到的左右端点 。
因为 的长度差 ,荒谬程度至少差 ,比末尾是 的差 更重要。所以要让 的长度最小。又因为输出要求的也是取最小的最优解,所以直接检验左端点 即可。
对于末尾是
的情况,同理可得,也应该取最小的可取的数。也就是直接left++
直到末尾是
为止,再检验一次即可。
【代码】
#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;
}