Digit Queries
題目
考慮一個按照遞增順序包含所有正整數的無窮字串:
12345678910111213141516171819202122232425...
你的任務是處理 個查詢:第 個字元是什麼數字?
輸入
- 第一行輸入一個正整數 ,代表查詢的數量。()
- 接著有 行,每行有一個正整數 。()
輸出
輸出 行,各自對應一個查詢。 對每個查詢,輸出字串第 個字元。
範例測資
Input :
3
7
19
12
Output :
7
4
1
解釋如下:
1234567891011121314151617181920...
^ ^ ^ ^
1 7 12 19
想法
我們可以找第 個字元落在哪個正整數 裡面,又是 從高位開始算起的哪一位數,從而找出答案。比如第 個字元落在正整數 裡面,並且是 從高位開始算起的第 位數,所以第 個字元是 2
。
要知道第 個字元落在正整數 裡面,我們可以透過觀察分析:
- 一位數有 到 ,共 個數字,佔去了前 個字元;
- 二位數有 到 ,共 個數字,佔去了接下來共 個字元;
- 三位數有 到 ,共 個數字,又佔去了接下來共 個字元。
而 ,表示第 個字元超過了整個一位數與二位數的區域,落在某個三位數裡面。而又因為 我們知道第 個字元又恰好超過了 個三位數,落在第 個三位數裡,那就是在正整數 裡面。更進一步因為 我們能知道它是正整數 從高位開始算起的第 位數,也就是 2
。
把這個流程一般化。我們可以發現 位數的正整數有 到 ,共 個數字。如果說第 個字元落在某個 位數裡面,那 就滿足 接著找到 使得 就代表第 個字元落在第 個 位數裡面,也就是在正整數 裡面。更進一步它會是正整數 從高位開始算起的第 位數。
範例程式碼
C++ 範例
#include <iostream>
#define int long long
using namespace std;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int q, k;
cin >> q;
while (q--) {
cin >> k;
int lv = 1, ten = 1;
while (k >= lv * 9 * ten) {
k -= lv * 9 * ten;
lv++;
ten *= 10;
}
int s = (k-1) / lv;
int n = ten + s;
for (int i = lv; i > k - s*lv; i--) {
n /= 10;
}
cout << n % 10 << '\n';
}
}