poj 1019 Number Sequence

7 篇文章 0 订阅

Description

A single positive integer i is given. Write a program to find the digit located in the position i in the sequence of number groups S1S2...Sk. Each group Sk consists of a sequence of positive integer numbers ranging from 1 to k, written one after another.
For example, the first 80 digits of the sequence are as follows:
11212312341234512345612345671234567812345678912345678910123456789101112345678910

Input

The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by one line for each test case. The line for a test case contains the single integer i (1 ≤ i ≤ 2147483647)

Output

There should be one output line per test case containing the digit located in the position i.

Sample Input

2
8
3

Sample Output

2
2

思路:设三个数组,n[i]表示数字i的长度,c[i]表示在字符串1234567891011....中数字i的结束位置,s[j]表示前j个字符串的长度,其中,第j个字符串以j结尾。

c[i] = c[i-1]+n[i]  s[i] = s[i-1]+c[i]

 1291011
n11122
c1(1)2(12)9 (123456789)11(1234567891011)13(1234567891011)
s1(1)3(112)

45(112123123412345123456

123456712345678123456789)

56(1121231234123451234561234567

1234567812345678912345678910)

69(1121231234123451234561234567

12345678123456789123456789101234567891011)

采用二分查找,设输入为num

首先从s数组中,查找num所在的第j个串,s[j]>=num && s[j-1]<num ,更新num的值为num -= s[j-1];

然后从数组c中确定为该串的哪一个数字,c[j] >= num && c[j-1] < num,更新num的值为num -=c[j-1]

到这一步,已经确定了num所在的数字以及为该数字的第几位,求出即可。

补充一个函数  lower_bound(),二分查找,数据升序排列

头文件:#include<algorithm>

使用 lower_bound(array,array+size,num) 返回数组array中第一个大于等于num的数,搜索区间[array,array+szie),左闭右开,如果所有元素均小于num,则返回array+size,返回的是指针。

使用:int index = lower_bound(array,array+size) - array; index为下标。

upper_bound(array,array+size,num) 返回数组array中第一个大于num的数

bool binary_search(array,array+size,num):二分查找,检查某个元素是否存在,

#include<iostream>
#include<algorithm>
#pragma warning(disable:4996)
using namespace std;
long long s[52850];
int c[52850],n[52850];
//s表示每一个串的长度 c[i]表示数字i在确定的串中的位置
int length(int i){
    if(i < 10)
        return 1;
    if(i <100)
        return 2;
    if(i <1000)
        return 3;
    if(i < 10000)
        return 4;
    return 5;
}
void init(){
    s[0] = 0;
    c[0] = 0;
    for(int i = 1; i <= 52849; i++){
        n[i] = length(i);
        c[i] = c[i-1]+n[i];
        s[i] = s[i-1]+c[i];
    }
}
int main(){
    int total_cases,left;
    cin>>total_cases;
    init();
    while(total_cases--){
        int num;
        cin>>num;
        //二分查找 lower_bound upper_bound  binary_search
        left = lower_bound(s+1,s+52845,num) - s;  //返回第一个大于等于num的值
        num -= s[left-1];
        left = lower_bound(c+1,c+left,num) - c;
        num-=c[left-1];
        num = n[left] - num+1;
        while(--num > 0)
            left/=10;
        cout<<left%10<<endl;
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值