Table of Contents

ExplanationImplementation

Explanation

Note that this is very tricky for a bronze problem!

Since kk can be as big as 101810^{18}, there is no way we can approach this problem through brute force. Instead, we'll need to work out an algorithm that can answer queries in logarithmic time.

Let's group numbers by how many digits they have. An observation we can make is that for any n1n \geq 1, there are 910n19 \cdot 10^{n-1} numbers in the group with numbers of length nn. Additionally, for each group, the total count of digits from all of the group's numbers combined is nn times how many numbers are in the group. For instance:

  • Length 11 numbers: 191\dots 9\rightarrow 99 numbers 19=9\rightarrow1\cdot9=9 digits total
  • Length 22 numbers: 109910\dots 99\rightarrow 9090 numbers 290=180\rightarrow2\cdot90=180 digits total
  • Length 33 numbers: 100999100\dots 999\rightarrow 900900 numbers 3900=2700\rightarrow3\cdot900=2700 digits total
  • And so on...

To find which group the number that contains the kkth digit is in, we can iterate through groups until the sum of the total number of digits from all the groups we've processed becomes greater than or equal to kk. In other words, we continue increasing the number of groups we look at (starting from 11-digit numbers) until the following is true:

n=1# of groupsn910n1k\sum^{\text{\# of groups}}_{n=1}{n\cdot9\cdot10^{n-1}\geq k}

Once the condition becomes true, we know that the kkth digit must fall into the last group used in the sum. We can now calculate the kkth digit's position in the group by subtracting kk by the total number of digits from all groups before it. We'll call this relative position jj:

j=k1n=1# of groups1n910n1j=k-1-\sum^{\text{\# of groups}-1}_{n=1}{n\cdot9\cdot10^{n-1}}

Note that we subtract 11 from the result in order to make jj 00-based (which makes it more convenient to solve the rest of the problem). For example, if j=0j=0, that would mean the kkth digit is the first digit in the group. If j=100j=100, that would mean the kkth digit is the 9999-th digit in the group, etc. From there, we can divide jj by nn (the length of the numbers in the group), which gives us the position of the number that contains the kkth digit within the group (also 00-based). Similarly as before, a position of 00 means that the number is the first number in the group, and a position of 100100 means that the number is the 9999-th number in the group.

To calculate the exact number the kkth digit is in, we can add the position of the number within the group (which we just found) to the value of the first number of the group, which is just 10n110^{n-1} (you can find this pattern from the beginning example). Now, all that's left is finding the position of the kk-th digit within the number that it's in. We can calculate that by taking jmodnj \bmod n, which finds the remainder of jj when divided by nn. For example, let's look at the first 1212 digits in the group with length 33 numbers:

Digit Sequence110000110011110022110033
Position0011223344556677889910101111

As you can see, for each 33-digit number in the digit sequence, the first digit is always at a position that's a multiple of 33, meaning the position modulo 33 equals 00. Similarly, the second digit in each number is always at a position that's 11 plus a multiple of 33, meaning its position modulo 33 equals 11. Finally, the third digit in each number is always 22 plus a multiple of 33, meaning that its position modulo 33 equals 22. This pattern extends for numbers of all sizes, and it is thus why we can use the modulo operator to determine the kkth digit's 00-based position within the number it's inside.

Now, we can calculate our answer by converting the number that the kkth digit is in into a string and indexing it at the position we've just found.

Implementation

Time Complexity: O(qlogk)\mathcal{O}(q\log{k})

C++

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// Returns 10 to the power of "exp"
// Not using pow() because it can be inaccurate for large powers
ll pow10(int exp) {
ll product = 1;
for (int i = 0; i < exp; i++) { product *= 10; }
return product;

Java

import java.io.*;
import java.util.*;
public class DigitQueries {
public static void main(String[] args) {
Kattio io = new Kattio();
int q = io.nextInt();
for (int i = 0; i < q; i++) {
long k = io.nextLong();

Python

for _ in range(int(input())):
k = int(input())
"""
Subtract k by sizes of groups until k becomes smaller than the size of the
current group. This produces the same effect as summing group sizes until
k becomes less than or equal to the sum. By the time the while loop ends,
k - 1 will equal j.
"""
n = 1
while k > n * 9 * 10 ** (n - 1):

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!