题解 P1895 【数字序列】
题目背景
查找数字
题目描述
在下列的无穷数字序列1121231234123451234561234567123456781234567891234567 8910123456789101112345678910......中,查找第i个数字。
输入输出格式
输入格式:
第一行为正整数t(1≤t≤10),表示测试数据组数。接下来t行,每行一个正整数i(1≤i≤2^31-1)。
输出格式:
对于每一个i,输出对应位置上的数字。
输入输出样例
输入样例#1: 复制
2
3
8
输出样例#1: 复制
2
2
主要思路:预处理 + lower_bound (STL大法好)
我们可以预处理一下一个数n的长度,预处理一下1n的长度,预处理一下1,12,13,...,1n的长度(听起来好麻烦的说)
预处理完毕以后,对于每一个查询n,我们可以用lower_bound找到第几位之前完整的1,12,13,...,1m,使得这个长度小于等于n且最大。然后再用lower_bound寻找最大的1k,使得这个长度小于等于n - length(1,12,13,...,1~m)且最大。这样就可以求出第n位所在的数中在第几位。所以我们只需要把第n位所在的数分解一下就好了。答案就是这个数的分解后第(n - length(1,12,13,...,1~m) - length(1~k))位
不太明白的话就手玩一下体会一下。
注意:
用可能减着减着,n会变成0,所以要加特判,当n减到0时,就把前面取到的数的最后一位输出即可
最近感冒QAQ有点晕
代码:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 100010
#define inf 2147483647
#define ll long long
#define ld long double
#define fi first
#define se second
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
//#define LOCAL
#define mod
#define Debug(...) fprintf(stderr, __VA_ARGS__)
inline int read(){
int f = 1, x = 0;char ch = getchar();
while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
//This is AC head above...
ll w[mn], a[mn], sum[mn], b[7];
int T, n;
inline void debug(int n = 20) {
go(i, 1, n, 1) printf("w[%2d] = %4d, a[%2d] = %4d, sum[%2d] = %4d\n", i, w[i], i, a[i], i, sum[i]);
}
int main(){
go(i, 0, 9, 1) w[i] = 1;
go(i, 10, 99, 1) w[i] = 2;
go(i, 100, 999, 1) w[i] = 3;
go(i, 1000, 9999, 1) w[i] = 4;
go(i, 10000, 99999, 1) w[i] = 5;
a[1] = w[1];
go(i, 2, 99999, 1) a[i] = a[i - 1] + w[i];
sum[1] = a[1];
go(i, 2, 99999, 1) sum[i] = sum[i - 1] + a[i];
// 这鬼畜的预处理啊QAQ
//debug();
T = read();
while(T--){
n = read();
int now = lower_bound(sum + 1, sum + 100000, n) - sum - 1;
n -= sum[now];
if(n == 0) {
cout << now % 10 << "\n";
continue;
}
now = lower_bound(a + 1, a + 100000, n) - a - 1;
n -= a[now];
if(n == 0) {
cout << now % 10 << "\n";
continue;
}
int nn = now + 1;
fo(i, w[now + 1], 1, 1) {
b[i] = nn % 10;
nn /= 10;
}
cout << b[n] << "\n";
}
#ifdef LOCAL
Debug("\nMy Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
NOIP2018并不是结束,而是开始