原题解析
题目的意思是,给定一串 0 到 9 的数字,问第 n 位的数字是几。
这串数字满足的规律是:
1121231234123451234561234567123456781234567891234567891012345678910111234567891011121234…
n 的范围是从 1 到 2147483647 。
题目要点
- 这串数字从 1 开始,并且第 1 位是 1 ;
- 2147483647 是最大 int ,因此涉及到求和至少也要用 uint 才装得下;
- 此题的规模为 O(n2),预计 2147483647 落在 31269 上,接近 5亿次运算的规模是接受不了的 ,必须优化;
- 利用 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;
}