ACM篇:POJ 1019--Number Sequence

来源:互联网 发布:淘宝详情免费视频 编辑:程序博客网 时间:2024/06/11 06:14

原题链接


思路:
f[i]表示以数字i结尾的序列总长度,如f[3] = 6
digits[i]表示以数字i结尾的一段单独序列的长度,如digits[6] = 6
先打表,然后二分查找距离目标最近的数字。

注意事项:
f[31268] = 2147523711
二分时注意左右范围。
我在最开始,取hi=32000,但f[] 尾末未赋值,导致对于非常大的输入数据查找失败,于是重另hi=31268。

#include <cstdio>#include <cstring>#include <cmath>const int MAXN = 31268;const int SUP = 2147483647;     long long f[MAXN+1];            // 31268----2147523711long long digits[MAXN+1];int ilen(int x){    return (int)(log10(x))+1;}void digits_count(){    digits[0] = f[0] = 0;    for (int i = 1; f[i-1] <= SUP; i++)    {        digits[i] = digits[i-1] + ilen(i);        f[i] = f[i-1] + digits[i];    }}int diary_search(int lo, int hi,long long arr[], int x){    int mid;    while (lo + 1 < hi)    {        mid = (lo + hi) >> 1;        if (arr[mid] <= x) lo = mid;        else hi = mid;    }    return lo;}void _print(int n, int poi)             // print the poith digit of n{    poi = log10(n) + 2 - poi;    printf("%d\n", n / (int)pow(10,poi-1) % 10);}int main(){       digits_count();    int T;    scanf("%d", &T);    while (T--)    {        int poi;        int n;        scanf("%d", &poi);        n = diary_search(1, MAXN, f, poi);      // n for f        if (f[n] == poi)        {            _print(n, ilen(n));            continue;        }        else         {            poi -= f[n];            n = diary_search(1, MAXN,digits, poi); // n for digits            if (digits[n] == poi)            {                _print(n , ilen(n));                continue;            }            else             {                poi -= digits[n];                _print(++n, poi);            }        }    }       return 0;} 
0 0
原创粉丝点击