All Euler problems
Project Euler

Rounded Square Roots

Define the "rounded square root" algorithm for a positive integer n: 1. Let d be the number of digits of n. 2. If d is odd, set x_0 = 2 x 10^((d-1)/2). If d is even, set x_0 = 7 x 10^((d-2)/2). 3....

Source sync Apr 19, 2026
Problem #0255
Level Level 15
Solved By 1,033
Languages C++, Python
Answer 4.4474011180
Length 362 words
geometrysequencelinear_algebra

Problem Statement

This archive keeps the full statement, math, and original media on the page.

We define the rounded-square-root of a positive integer $n$ as the square root of $n$ rounded to the nearest integer.

The following procedure (essentially Heron's method adapted to integer arithmetic) finds the rounded-square-root of $n$:

Let $d$ be the number of digits of the number $n$.

If $d$ is odd, set $x_0 = 2 \times 10^{(d-1)/2}$.

If $d$ is even, set $x_0 = 7 \times 10^{(d-2)/2}$.

Repeat: $$x_{k+1} = \Biggl\lfloor{\dfrac{x_k + \lceil{n / x_k}\rceil}{2}}\Biggr\rfloor$$ until $x_{k+1} = x_k$.

As an example, let us find the rounded-square-root of $n = 4321$.

$n$ has $4$ digits, so $x_0 = 7 \times 10^{(4-2)/2} = 70$.

$x_0 = 7 \times 10^{(4-2)/2} = 70$.

$$x_1 = \Biggl\lfloor{\dfrac{70 + \lceil{4321 / 70}\rceil}{2}}\Biggr\rfloor = 66$$ $$x_2 = \Biggl\lfloor{\dfrac{66 + \lceil{4321 / 66}\rceil}{2}}\Biggr\rfloor = 66$$ Since $x_2 = x_1$, we stop here.

So, after just two iterations, we have found that the rounded-square-root of $4321$ is $66$ (the actual square root is $65.7343137\cdots$).

The number of iterations required when using this method is surprisingly low.

For example, we can find the rounded-square-root of a $5$-digit integer ($10\,000 \le n \le 99\,999$) with an average of $3.2102888889$ iterations (the average value was rounded to $10$ decimal places).

Using the procedure described above, what is the average number of iterations required to find the rounded-square-root of a $14$-digit number ($10^{13} \le n < 10^{14}$)?

Give your answer rounded to $10$ decimal places.

Note: The symbols $\lfloor x \rfloor$ and $\lceil x \rceil$ represent the floor function and ceiling function respectively.

Problem 255: Rounded Square Roots

Mathematical Foundation

Lemma 1 (Fixed Range). All integers in [1013,1014)[10^{13}, 10^{14}) have exactly d=14d = 14 digits (even), so the initial guess is x0=7×106x_0 = 7 \times 10^6.

Proof. An integer nn has dd digits if and only if 10d1n<10d10^{d-1} \le n < 10^d. For n[1013,1014)n \in [10^{13}, 10^{14}), we have d=14d = 14. Since dd is even, x0=7×10(142)/2=7,000,000x_0 = 7 \times 10^{(14-2)/2} = 7{,}000{,}000. \square

Theorem 1 (Convergence). The iteration xk+1=(xk+n/xk)/2x_{k+1} = \lfloor (x_k + \lceil n/x_k \rceil)/2 \rfloor is an integer variant of Newton’s method for n\sqrt{n}. For any n1n \ge 1 and any initial x01x_0 \ge 1, the sequence (xk)(x_k) converges to a fixed point xx^* satisfying x(x1)<nx(x+1)x^*(x^*-1) < n \le x^*(x^*+1), i.e., xx^* is the nearest integer to n\sqrt{n} (rounded up on half-integers).

Proof. Newton’s method for f(x)=x2nf(x) = x^2 - n gives the iteration x(x+n/x)/2x \mapsto (x + n/x)/2. The integer variant uses ceiling division and floor of the average. One can verify:

  1. If xk>xx_k > x^*, then n/xkxk\lceil n/x_k \rceil \le x_k, and xk+1xkx_{k+1} \le x_k (the sequence is non-increasing once above the fixed point).
  2. If xkxx_k \le x^*, then n/xkxk\lceil n/x_k \rceil \ge x_k, and xk+1xkx_{k+1} \ge x_k.
  3. The sequence is eventually monotone and bounded, hence convergent.

The fixed-point condition x=(x+n/x)/2x^* = \lfloor (x^* + \lceil n/x^* \rceil)/2 \rfloor characterizes xx^* as the rounded square root. \square

Theorem 2 (Grouping by Quotient). For fixed xkx_k, the values of n[L,R]n \in [L, R] producing a given ceiling quotient q=n/xkq = \lceil n/x_k \rceil form the interval n[(q1)xk+1,  qxk]n \in [(q-1)x_k + 1, \; qx_k]. The next iterate is then xk+1=(xk+q)/2x_{k+1} = \lfloor (x_k + q)/2 \rfloor, which is constant over this interval.

Proof. By definition of ceiling division, n/xk=q\lceil n/x_k \rceil = q iff (q1)xk<nqxk(q-1)x_k < n \le qx_k, i.e., n[(q1)xk+1,qxk]n \in [(q-1)x_k + 1, qx_k]. Since xk+1x_{k+1} depends on nn only through qq, all nn in this interval share the same xk+1x_{k+1}. \square

Editorial

Average number of iterations of the rounded square root algorithm for n from 10^13 to 10^14 - 1. All numbers have 14 digits (even), so x0 = 7 * 10^6 = 7000000. Iteration: x_{k+1} = floor((x_k + ceil(n/x_k)) / 2) Stop when x_{k+1} == x_k. Interval-based approach: track (x_current, n_lo, n_hi) and split by ceil(n/x) values at each step. We use a map: x_value -> count_of_n_values. We then initially, all n in [N_lo, N_hi] start with x = x0. Finally, converged: these n values took iteration iterations.

Pseudocode

Use a map: x_value -> count_of_n_values
Initially, all n in [N_lo, N_hi] start with x = x0
For each distinct q = ceil(n/x), compute x_next
Converged: these n values took `iteration` iterations
else
Continue iterating: group by x_next

Complexity Analysis

  • Time: At each iteration, the number of groups is O(N)O(\sqrt{N}) (since the number of distinct ceiling quotients for a given xx over [Nlo,Nhi][N_{\text{lo}}, N_{\text{hi}}] is O(N)O(\sqrt{N}) by the divisor-bound argument). With O(logN)O(\log N) iterations, the total is O(NlogN)O(\sqrt{N} \log N). For N=1014N = 10^{14}: approximately 107×475×10810^7 \times 47 \approx 5 \times 10^8.
  • Space: O(N)O(\sqrt{N}) for storing the groups at each iteration level.

Answer

4.4474011180\boxed{4.4474011180}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_255/solution.cpp
#include <bits/stdc++.h>
using namespace std;

/*
 * Problem 255: Rounded Square Roots
 *
 * For n from 10^13 to 10^14-1 (14 digits, d=14, even): x0 = 7*10^6
 * Iteration: x_{k+1} = floor((x_k + ceil(n/x_k)) / 2)
 * Stop when x_{k+1} == x_k.
 *
 * Interval-based approach: track (x, n_lo, n_hi) groups and split by
 * ceil(n/x) values at each step. For fixed x, x_next = floor((x+q)/2)
 * where q = ceil(n/x). Each x_next value corresponds to 2 consecutive q values.
 *
 * Answer: 4.4474011180
 */

typedef long long ll;

ll ceildiv(ll a, ll b) {
    return (a + b - 1) / b;
}

int main(){
    const ll N_LO = 10000000000000LL;
    const ll N_HI = 99999999999999LL;
    const ll TOTAL = N_HI - N_LO + 1;
    const int x0 = 7000000;

    struct Interval {
        int x;
        ll nlo, nhi;
    };

    vector<Interval> current;
    current.push_back({x0, N_LO, N_HI});

    long double total_iterations = 0;

    while (!current.empty()) {
        // Process one iteration
        map<int, vector<pair<ll,ll>>> next_map;
        ll converged_count = 0;
        // We need iteration number for weighting. Track separately.
        // Actually we increment a counter.
        static int iter = 0;
        iter++;

        for (auto& [x, nlo, nhi] : current) {
            ll q_lo = ceildiv(nlo, (ll)x);
            ll q_hi = ceildiv(nhi, (ll)x);
            ll xn_lo = ((ll)x + q_lo) / 2;
            ll xn_hi = ((ll)x + q_hi) / 2;

            for (ll xn = xn_lo; xn <= xn_hi; xn++) {
                ll q1 = max(2LL * xn - x, q_lo);
                ll q2 = min(2LL * xn + 1 - x, q_hi);
                if (q1 > q2) continue;

                ll n1 = max((q1 - 1) * x + 1, nlo);
                ll n2 = min(q2 * x, nhi);
                if (n1 > n2) continue;

                if (xn == x) {
                    converged_count += n2 - n1 + 1;
                } else {
                    next_map[(int)xn].push_back({n1, n2});
                }
            }
        }

        total_iterations += (long double)converged_count * iter;

        current.clear();
        for (auto& [xn, intervals] : next_map) {
            sort(intervals.begin(), intervals.end());
            ll lo = intervals[0].first, hi = intervals[0].second;
            for (size_t i = 1; i < intervals.size(); i++) {
                if (intervals[i].first <= hi + 1) {
                    hi = max(hi, intervals[i].second);
                } else {
                    current.push_back({xn, lo, hi});
                    lo = intervals[i].first;
                    hi = intervals[i].second;
                }
            }
            current.push_back({xn, lo, hi});
        }
    }

    long double avg = total_iterations / (long double)TOTAL;
    printf("%.10Lf\n", avg);
    return 0;
}