Nature Numbers hiho一下 第180周

题意: 将自然数从 0 开始一直往后写,形成一个数组:”012345678910111213…”。求数组的第 N 位上的数字是几,数组从下标为 0 开始,即第 0 位上的数字是 0,第 1 位上的数字是 1,以此类推。

思路: N 的范围较大,考虑如何减少时间复杂度。稍微列举下我们能够写出 1 位数的下标范围、2 位数的下标范围等,然后我们能够发现 17 位数的下标范围的右端点就已经超出了 1018

要求第 N 个位置上的数字是几,我的思路是求出第 N 个位置对应的数和第 N 个位置上的数字是当前数的第几位。
举个例子,当 N = 17 时,情况如下图:

N = 17 对应的数是 13 的 从右往左数的第一位数 3。

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;
typedef long long LL;

const LL base[] = {1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18}; //存储 10 的 i 次方
LL t[20][2]; //t[i][0] 表示当前段左端点下标,t[i][1] 表示当前段右端点下标
LL N;

//返回数 num 从右往左数的第 pos 位上的数字
LL Colc(LL num, LL pos)
{
    while(pos > 1){
        num /= 10;
        pos--;
    }
    return num % 10;
}

int main()
{
    //产生每段的范围
    t[1][0] = 0; t[1][1] = 9;
    for(LL i=2; i<=17; i++){
        t[i][0] = t[i-1][1]+1;
        t[i][1] = t[i-1][1]+9*base[i-1]*i;
    }

    while(scanf("%lld", &N) == 1){
        LL dig;  //dig 表示下标为 N 的位置对应的数字是 dig 位数
        for(dig=1; dig<=17; dig++){
            if(N >= t[dig][0] && N <= t[dig][1])
                break;
        }

        if(dig == 1){  //如果是 1 位数
            printf("%d\n", N);
        }else{         //不是 1 位数
            LL num = base[dig-1]+(N - t[dig][0])/dig;  //num 表示下标为 N 的位置对应的数字是多少
            LL pos = (N - t[dig][0])%dig;
            pos = dig - pos;  //pos 表示下标为 N 的位置上的数字是当前对应数从右往左数的第 pos 位上的数字

            printf("%lld\n", Colc(num, pos));
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值