Little Sub and Mr.Potato's Math Problem (构造法)

题目传送门
Little Sub and Mr.Potato's Math Problem

Time Limit: 2 Seconds       Memory Limit: 65536 KB

Little Sub loves math very much. He enjoys counting numbers.

One day, Mr.Potato gives him an interesting math problem. Please help Little Sub solve this problem.

Let's sort the integers  according to alphabetical order. For example, when , the order should be: .

We define  as the position of number  in the sorted  numbers. For example, .

Given  and , please find the smallest  such that .

Input

There are multiple test cases. The first line of the input contains an integer  (), indicating the number of test cases. For each test case:

The first and only line contains two integers  and  ().

Output

For each test case, please output the answer in one line. If there is no such , please output "0" (without quotes).

Sample Input
2
2 4
10000001 100000000
Sample Output
11
1000000088888880

题意:如上题

思路:

第一步:我们可以先计算出当前的数前面按照字典序的话,前面有多少数(包括自己)。

(具体计算过程,456.首先是三位数的数在456前面的个数,就是(100->456),然后再就是两位数(10-45),然后再就是一位数1-4,严格遵守字典序)。

第二步:如果说当前的数前面的数的个数大于m的话,这个时候肯定是不符合情况的,如果说刚好凑起来的话,这个时候输出k就可以了。

第三步:经过了第二步,发现当前的数N取k的时候凑不起来,我们就需要通过增加n来使得k的位数往后移动。举个例子,456不够,我们就可以通过添加1000-4560之间的数来使得456的位数往后移动,如果还不够我们就添加10000-45600之间的数使得456的位数往后移动。

第四步:我们需要判断一种特殊情况,比如说 10 10这个样例,10前面的数只有1,但是你如果加100之后的,也不会使得10的位数往后移动,这个时候就应该输出0。(就是这些数的字典序是相对固定的)

代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int T;
int k,m;
ll base=1;

ll get_num(ll x)
{
    ll ans=0;
    ll tmp=x;
    while(x){
        base*=10;
        x/=10;
    }
    base/=10;
    ll base1=base;
    while(tmp)
    {
        ans+=(tmp-base1)+1;
        tmp/=10;
        base1/=10;
    }
    return ans;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&k,&m);
        base=1;
        ll tmp=get_num(k);
        m-=tmp;
        if(m<0) printf("0\n");
        else if(m==0) printf("%d\n",k);
        else if(base==k) printf("0\n");
        else{
          ll ans=k-base;
          base*=10;
          ans*=10;
          while(m>ans)
          {
             m-=ans;
             ans*=10;
             base*=10;
          }
          printf("%lld\n",base+m-1);
        }
    }
    return 0;
}
View Code

参考博客:https://www.cnblogs.com/letlifestop/p/10294237.html



转载于:https://www.cnblogs.com/zhgyki/p/10370860.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值