題解 P1895 【數字序列】
阿新 • • 發佈:2018-12-03
題目背景
查詢數字
題目描述
在下列的無窮數字序列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; }