Topics

We are given a recursively defined sequence of strings:

  • “What are you doing at the end of the world? Are you busy? Will you save us?”
  • For , “What are you doing while sending ""? Are you busy? Will you send ""?”

Given and , we need to find the -th character of string , or return ’.’ if exceeds the length of .

Idea

Let’s break down the pattern to understand the recursive structure. Let’s define:

  • “What are you doing at the end of the world? Are you busy? Will you save us?”
  • “What are you doing while sending ""
  • ""? Are you busy? Will you send ""
  • ""?”

Now we can rewrite our recursive definitions:

  • for

Calculating String Lengths

Before we can find the -th character, we need to know the length of each string :
Let’s define as the length of string :

  • for

However, for large , length can quickly exceed the range of standard integer types. We’ll need to handle potential overflow carefully.

Finding the K-th Character

Once we know the length of the strings, we can find the -th character recursively:

  1. If , return '.'
  2. If , return the -th character of string
  3. If , return the -th character of string
  4. If , find the -th character of
  5. If , return the -th character of string
  6. If , find the -th character of
  7. Otherwise, return the -th character of string

Time Complexity: per query
Space Complexity: for precompting the lengths

Code

const string A = "What are you doing at the end of the world? Are you busy? "
                 "Will you save us?";
const string B = "What are you doing while sending \"";
const string C = "\"? Are you busy? Will you send \"";
const string D = "\"?";
 
vector<ll> lengthCache;
 
void precomputeLengths() {
  const ll MAX_N = 1e5 + 5;
  lengthCache.push_back(A.length());
 
  for (int i = 1; i <= MAX_N; i++) {
    // Check for potential overflow
    if (lengthCache[i - 1] >
        (LLONG_MAX - B.length() - C.length() - D.length()) / 2) {
      lengthCache.push_back(LLONG_MAX); // Mark as overflow
    } else {
      lengthCache.push_back(B.length() + C.length() + D.length() +
                            2 * lengthCache[i - 1]);
    }
  }
}
 
ll getLength(int n) {
  if (n < lengthCache.size())
    return lengthCache[n];
  return LLONG_MAX; // For very large n, length will exceed any possible k
}
 
char findKthCharacter(int n, ll k) {
  if (k > getLength(n))
    return '.';
 
  if (n == 0)
    return A[k - 1];
 
  // Check in which part of the string the kth character lies
  if (k <= B.length()) {
    return B[k - 1];
  }
 
  k -= B.length();
  ll prevLength = getLength(n - 1);
 
  if (k <= prevLength) {
    return findKthCharacter(n - 1, k);
  }
 
  k -= prevLength;
 
  if (k <= C.length()) {
    return C[k - 1];
  }
 
  k -= C.length();
 
  if (k <= prevLength) {
    return findKthCharacter(n - 1, k);
  }
 
  k -= prevLength;
 
  return D[k - 1];
}
 
void solve() {
  precomputeLengths();
 
  int q;
  cin >> q;
 
  string result;
  for (int i = 0; i < q; i++) {
    int n;
    ll k;
    cin >> n >> k;
 
    result += findKthCharacter(n, k);
  }
 
  cout << result << endl;
}