码迷,mamicode.com
首页 > 其他好文 > 详细

【POJ 1019】 Number Sequence

时间:2015-08-19 16:51:27      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:二分

【POJ 1019】 Number Sequence


二分水题 放组合数学里。。。可能有什么正规姿势吧Orz


112123123412345...这种串 分成长度1 2 3 4 5...的串 注意有多位数

把长度累加到一个数组里 注意要累加 因为查询的时候查的是原串中对应位置的数 因此要累加上前一次的长度 然后二分处该串前的总长 用查询的位置-之前串的总长 就是在最长的串中的位置 因此还要打个最长串的表


这些我都写一个循环里了 看着有点乱 可以拆开写。。。


代码如下:


#include <iostream>
#include <cstdio>
#include <cstdlib>
#define ll long long
#define INF 2147483648

using namespace std;
//2147483647
ll r[33333];   //二分查的数组
char str[233333]; //最长串的表
int tp,len;                     //累计二分数组长度 和最长串长度

void Init()
{
    int i,j,cnt,pw,k,s;
    r[0] = 0;
    len = 1;          //最长串从1开始 便于查询
    for(tp = 1, i = 1, j = 1, cnt = 1, pw = 10; r[tp-1] <= 2147483647; i += cnt, tp++) //i累计当前串长 cnt累计最后一个数长度  j累计最后一个数(多位数) pw最后一个数位(1 10 100 100...)
    {
        r[tp] = r[tp-1] + i;
        k = j;
        s = pw/10;
        while(s)
        {
            str[len++] = k/s + '0';
            k%=s;
            s /= 10;
        }

        ++j;
        if(j/pw)
        {
            pw *= 10;
            cnt++;
        }
    }
    tp--;
    r[tp] = INF;
}

int main()
{
    int l,rr,ans,t,mid;
    ll pos;
    Init();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld",&pos);
        l = ans = 0, rr = tp;

        while(l <= rr) //二分查找
        {
            mid = l+rr>>1;
            if(r[mid] < pos)
            {
                ans = mid;//小于查询位置的数中最大的 注意不可等
                l = mid+1;
            }else rr = mid-1;
        }
        printf("%c\n",str[pos-r[ans]]);
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

【POJ 1019】 Number Sequence

标签:二分

原文地址:http://blog.csdn.net/challengerrumble/article/details/47781475

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!