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:
- If , return
'.'
- If , return the -th character of string
- If , return the -th character of string
- If , find the -th character of
- If , return the -th character of string
- If , find the -th character of
- 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;
}