Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Don’t try to build the string. The prefix crosses whole blocks: all -digit numbers, then all -digit numbers, then all -digit numbers, etc.
For a fixed length , there are numbers, so that whole block contributes digits. Peel off complete blocks while is bigger than that.
After removing complete blocks, you are inside the block of -digit numbers starting at . If , then complete numbers are fully included, and digits of the next number are included.
So the only real subproblem is: compute the sum of digits of every number from to quickly. Use the standard per-decimal-position formula with high, cur, and low.
For place value , split as high | cur | low. Digits smaller than cur contribute , completed cycles contribute , and the current digit contributes . Then use range sums to handle the complete numbers inside the final block.
We need the sum of digits in
cut after exactly digits.
The main trap is thinking about the sequence as a string. That string has length in the biggest case, so yeah, that plan gets nuked from orbit. Work with blocks instead.
Block Structure
Group numbers by digit length:
For length :
So we can repeatedly remove whole blocks from .
When we remove a whole block, we also add the sum of digits of all numbers in that block.
Eventually, lands inside one specific block of -digit numbers.
What Happens Inside The Final Block
Suppose after removing earlier blocks, we are inside the -digit block.
Let
The remaining prefix includes:
complete numbers, namely
and then
digits from the next number:
So the answer is:
That reduces the problem to one helper: quickly compute the sum of digits from to .
Digit Sum From To
Let be the sum of all digits appearing in all numbers from to .
We compute contribution independently for every decimal place .
For a fixed place , split like this:
Now count the contribution of this digit position.
Every full cycle of length contains each digit exactly times at this position. The sum per full cycle is:
There are high full cycles, so that gives:
Then comes the partial cycle.
Digits smaller than cur have already appeared for a full run of length each:
so they contribute:
Finally, digit cur appears for the last numbers, contributing:
So this position contributes:
Sum that over all powers of , and we get .
Then the sum of digits from to is just:
Putting It Together
For each test case:
The largest is only , so there are fewer than digit lengths. Each call to also checks fewer than decimal positions. Tiny.
Complexity
Per test case:
Memory:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll sumTo(ll n) {
if (n <= 0) return 0;
__int128 ans = 0;
for (ll p = 1; p <= n; p *= 10) {
ll high = n / (p * 10);
ll cur = (n / p) % 10;
ll low = n % p;
ans += (__int128)high * 45 * p;
ans += (__int128)cur * (cur - 1) / 2 * p;
ans += (__int128)cur * (low + 1);
if (p > LLONG_MAX / 10) break;
}
return (ll)ans;
}
ll rangeSum(ll l, ll r) {
if (l > r) return 0;
return sumTo(r) - sumTo(l - 1);
}
int main() {
setIO();
vector<ll> pow10(19, 1);
for (int i = 1; i < 19; i++) pow10[i] = pow10[i - 1] * 10;
int t;
cin >> t;
while (t--) {
ll k;
cin >> k;
ll ans = 0;
int d = 1;
while (true) {
ll start = pow10[d - 1];
ll cnt = 9 * start;
__int128 blockDigits = (__int128)cnt * d;
if (blockDigits > k) break;
ans += rangeSum(start, start + cnt - 1);
k -= (ll)blockDigits;
d++;
}
ll start = pow10[d - 1];
ll full = k / d;
int rem = k % d;
ans += rangeSum(start, start + full - 1);
string next = to_string(start + full);
for (int i = 0; i < rem; i++) ans += next[i] - '0';
cout << ans << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll sumTo(ll n) {
if (n <= 0) return 0;
__int128 ans = 0;
for (ll p = 1; p <= n; p *= 10) {
ll high = n / (p * 10);
ll cur = (n / p) % 10;
ll low = n % p;
ans += (__int128)high * 45 * p;
ans += (__int128)cur * (cur - 1) / 2 * p;
ans += (__int128)cur * (low + 1);
if (p > LLONG_MAX / 10) break;
}
return (ll)ans;
}
ll rangeSum(ll l, ll r) {
if (l > r) return 0;
return sumTo(r) - sumTo(l - 1);
}
int main() {
setIO();
vector<ll> pow10(19, 1);
for (int i = 1; i < 19; i++) pow10[i] = pow10[i - 1] * 10;
int t;
cin >> t;
while (t--) {
ll k;
cin >> k;
ll ans = 0;
int d = 1;
while (true) {
ll start = pow10[d - 1];
ll cnt = 9 * start;
__int128 blockDigits = (__int128)cnt * d;
if (blockDigits > k) break;
ans += rangeSum(start, start + cnt - 1);
k -= (ll)blockDigits;
d++;
}
ll start = pow10[d - 1];
ll full = k / d;
int rem = k % d;
ans += rangeSum(start, start + full - 1);
string next = to_string(start + full);
for (int i = 0; i < rem; i++) ans += next[i] - '0';
cout << ans << '\n';
}
}