POJ1019 - Number Sequence 解题报告

POJ1019 - Number Sequence 解题报告

原题解析

题目的意思是,给定一串 0 到 9 的数字,问第 n 位的数字是几。
这串数字满足的规律是:
1121231234123451234561234567123456781234567891234567891012345678910111234567891011121234…
n 的范围是从 1 到 2147483647 。

题目要点

  1. 这串数字从 1 开始,并且第 1 位是 1 ;
  2. 2147483647 是最大 int ,因此涉及到求和至少也要用 uint 才装得下;
  3. 此题的规模为 O(n2),预计 2147483647 落在 31269 上,接近 5亿次运算的规模是接受不了的 ,必须优化;
  4. 利用 dp 空间换时间,优化到 O(n);

优化

首先,考虑将 1 行数字变成 n 行数字,既:

1
12
123

求出每一行的长度,得到递推公式:

a[1] = 1
a[n] = a[n-1] + digit(n)

这样可以同时求出每一行的累计长度:

s[1] = 1
s[n] = s[n-1] + a[n]

这样就可以在 O(n) 的复杂度内,找到第 n 位落在哪个数上。

示例代码

#include <math.h>
#include <stdio.h>
#include <algorithm>

#define digit(x) (log10(double(x)) + 1)
#define Max 31270

struct PreData
{
   
    unsigned int a[Max];
    unsigned int s[Max];
};

struct State
{
   
    State(const PreData& d)
        : data(d)
    {
   }

    int index;
    int result;

    const PreData& data;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值