D - 183184 Editorial by en_translator
Observations
Consider the case where \((C + x)\) has \(d\) digits. Then \(x\) must fall into the intersection of:
- \(1 \leq x \leq D\), and
- \(10^{d-1} - C \leq x \leq 10^d - 1 - C\).
Let \(L = \mathrm{max}(1, 10^{d-1} - C)\) and \(R = \mathrm{min}(D, 10^d - 1 - C)\). If \(L > R\), there is no such \(x\); if \(L \leq R\), it can take \(L \leq x \leq R\).
Since we assumed that \((C + x)\) has \(d\) digits, \(f(C, C+x) = C \times 10^d + (C+x)\). Thus, the answer for this range is the number of perfect squares between \(C \times 10^d + C + L\) and\(C \times 10^d + C + R\), inclusive.
As there are \(\lfloor \sqrt{k} \rfloor\) perfect squares less than or equal to \(k\), the sought count can be represented as \(\lfloor \sqrt{C \times 10^d + C + R} \rfloor - \lfloor \sqrt{C \times 10^d + C + L - 1} \rfloor\).
To find \(\lfloor \sqrt{k} \rfloor\), it is faster to use std::sqrt instead of performing a binary search.
The answer to the original problem can be found as the sum of the counts in the computation above for \(d = 1, \dots, \lfloor \log_{10} (C+D) \rfloor + 1\).
Assuming that square roots can be found in a constant time, the time complexity is \(O(\log(C+D))\), which is fast enough.
Sample code (C++)
#include <iostream>
using std::cin;
using std::cout;
using std::min;
using std::max;
#include <cmath>
typedef long long int ll;
// floor(sqrt(x))
ll f (ll x) {
ll y = sqrt(x);
while (y * y > x) y--;
while ((y+1) * (y+1) <= x) y++;
return y;
}
ll solve (ll c, ll d) {
ll ans = 0;
ll xmin = 1, xmax = 9, cshift = 10;
while (xmin <= c + d) {
ll l = max(xmin, c + 1);
ll r = min(xmax, c + d);
if (l <= r) {
ll vl = c * cshift + l;
ll vr = c * cshift + r;
ans += (f(vr) - f(vl - 1));
}
xmin = xmin * 10;
xmax = (xmax + 1) * 10 - 1;
cshift *= 10;
}
return ans;
}
int main (void) {
ll T;
cin >> T;
for (ll ti = 0; ti < T; ti++) {
ll c, d;
cin >> c >> d;
ll ans = solve(c, d);
cout << ans << "\n";
}
return 0;
}
posted:
last update: