1. 程式人生 > >題解 P1895 【數字序列】

題解 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的長度,預處理一下1~n的長度,預處理一下1,1~2,1~3,...,1~n的長度(聽起來好麻煩的說)

預處理完畢以後,對於每一個查詢n,我們可以用lower_bound找到第幾位之前完整的1,1~2,1~3,...,1~m,使得這個長度小於等於n且最大。然後再用lower_bound尋找最大的1~k,使得這個長度小於等於n - length(1,1~2,1~3,...,1~m)且最大。這樣就可以求出第n位所在的數中在第幾位。所以我們只需要把第n位所在的數分解一下就好了。答案就是這個數的分解後第(n - length(1,1~2,1~3,...,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;
}