【POJ 1019】 Number Sequence

【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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值