Problem 925: Larger Digit Permutation III

View on Project Euler

Project Euler Problem 925 Solution

EulerSolve provides an optimized solution for Project Euler Problem 925, Larger Digit Permutation III, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary Let \(P(x)\) denote the next lexicographically larger permutation of the decimal digits of \(x\). If the digits of \(x\) are already in nonincreasing order, then no larger permutation exists and we define \(P(x)=0\). Problem 925 asks for $$S(k)=\sum_{n=1}^{10^k-1} P(n^2)\pmod{10^9+7}.$$ For \(k=16\), a direct loop over all \(10^{16}-1\) roots is impossible. The solutions therefore do not enumerate roots one by one. Instead they group roots by decimal suffixes and exploit the fact that the low digits of a square depend only on the low digits of the root. Mathematical Approach The core idea is to reveal the square from right to left. As soon as the decisive ascent for the next-permutation operation is known, an entire block of roots can be collapsed into a single contribution. Separating the easy square-sum term from the permutation correction Introduce the digit-permutation correction $$\Delta(x)=\begin{cases} P(x)-x,&\text{if a larger digit permutation exists},\\ -x,&\text{otherwise}. \end{cases}$$ Then \(x+\Delta(x)=P(x)\), with the second line exactly encoding the convention \(P(x)=0\). Hence $$S(k)\equiv \sum_{n=1}^{10^k-1} n^2+\sum_{n=1}^{10^k-1}\Delta(n^2)\pmod{10^9+7}.$$ The first sum is closed form....

Detailed mathematical approach

Problem Summary

Let \(P(x)\) denote the next lexicographically larger permutation of the decimal digits of \(x\). If the digits of \(x\) are already in nonincreasing order, then no larger permutation exists and we define \(P(x)=0\). Problem 925 asks for

$$S(k)=\sum_{n=1}^{10^k-1} P(n^2)\pmod{10^9+7}.$$

For \(k=16\), a direct loop over all \(10^{16}-1\) roots is impossible. The solutions therefore do not enumerate roots one by one. Instead they group roots by decimal suffixes and exploit the fact that the low digits of a square depend only on the low digits of the root.

Mathematical Approach

The core idea is to reveal the square from right to left. As soon as the decisive ascent for the next-permutation operation is known, an entire block of roots can be collapsed into a single contribution.

Separating the easy square-sum term from the permutation correction

Introduce the digit-permutation correction

$$\Delta(x)=\begin{cases} P(x)-x,&\text{if a larger digit permutation exists},\\ -x,&\text{otherwise}. \end{cases}$$

Then \(x+\Delta(x)=P(x)\), with the second line exactly encoding the convention \(P(x)=0\). Hence

$$S(k)\equiv \sum_{n=1}^{10^k-1} n^2+\sum_{n=1}^{10^k-1}\Delta(n^2)\pmod{10^9+7}.$$

The first sum is closed form. Writing \(N=10^k\),

$$\sum_{n=1}^{10^k-1} n^2=\sum_{n=0}^{N-1} n^2=\frac{N(N-1)(2N-1)}{6}.$$

So the real problem is to evaluate the correction sum efficiently.

Encoding a root by trailing zeros and a revealed suffix

Every positive root \(n<10^k\) can be written uniquely as

$$n=(q\,10^\ell+r)\,10^t,$$

where \(t\ge 0\) is the number of trailing zeros, \(r\) is an \(\ell\)-digit suffix block whose rightmost digit is nonzero, and \(q\) is the still-unknown higher prefix. In the state description, leading zeros inside the width-\(\ell\) block are allowed; that is why blocks such as \(01\) genuinely occur in the recursion.

The implementations start from a one-digit nonzero block \(r=d\in\{1,\dots,9\}\), choose \(t\in\{0,\dots,k-1\}\), and then prepend new digits on the left. Once \(\ell+t\ge k\), every root digit has been fixed and the recursion stops.

The square-suffix invariant

For a fixed state \((r,\ell,t)\), all completions share the same low square digits because

$$n^2=(q\,10^\ell+r)^2\,10^{2t}\equiv r^2\,10^{2t}\pmod{10^{\ell+2t}}.$$

Thus the lowest \(\ell+2t\) digits of \(n^2\) are already determined by the revealed root suffix and by the trailing-zero count. If we prepend a new digit \(d\in\{0,\dots,9\}\) and set

$$r'=d\,10^\ell+r,$$

then one more square digit becomes visible:

$$n^2\equiv (r')^2\,10^{2t}\pmod{10^{\ell+1+2t}}.$$

The recursion therefore grows a known square suffix one decimal place at a time.

Detecting the exact moment when the next-permutation pivot is fixed

Let the width-\(\ell\) decimal block representing \(r^2\bmod 10^\ell\) be padded with leading zeros if necessary. A crucial invariant is that this block is nonincreasing from left to right in every recursive state that continues deeper. The base case \(\ell=1\) is trivial, and the recursion preserves the invariant precisely by deciding whether to continue or to collapse the branch.

Write

$$a=\left\lfloor\frac{r^2\bmod 10^\ell}{10^{\ell-1}}\right\rfloor,\qquad b=\left\lfloor\frac{(r')^2\bmod 10^{\ell+1}}{10^\ell}\right\rfloor.$$

Here \(a\) is the leftmost digit of the current known square suffix, and \(b\) is the new digit inserted immediately to its left.

If \(b\ge a\), then the enlarged \((\ell+1)\)-digit suffix is still nonincreasing, so the rightmost ascent needed by the next-permutation algorithm has not appeared yet. The branch must be extended further.

If \(b<a\), then the digits to the right were already nonincreasing, and the first ascent from the right is now exactly the boundary \(b\mid a\). That means the pivot of the next-permutation operation has been located completely inside the revealed suffix. Digits farther to the left will remain untouched by the permutation step, so the correction \(\Delta(n^2)\) no longer depends on the unrevealed higher prefix.

Collapsing an entire block of higher prefixes

After prepending \(d\), there remain

$$m=k-\ell-t-1$$

root digits that have not been chosen yet. There are therefore \(10^m\) completions of the current root state. All corresponding squares share the same revealed suffix

$$u=\big((r')^2\bmod 10^{\ell+1}\big)\,10^{2t}.$$

Once \(b<a\), every completion whose square has a genuine nonzero prefix to the left of that suffix has the same correction as the representative number \(10^{\ell+1+2t}+u\). This representative need not itself be a square; it is only a convenient number with the same decisive suffix and with a real digit to the left of it.

The only subtle case is the completion with empty higher root prefix. If \((r')^2<10^{\ell+1}\), then that completion produces the actual square \(u\), where the apparent leading zero in the width-\((\ell+1)\) block was only padding. In that one case we must use \(\Delta(u)\) rather than the positive-prefix representative.

So the whole block contributes

$$C(r',\ell+1,t)= \begin{cases} \Delta(u)+(10^m-1)\,\Delta\!\left(10^{\ell+1+2t}+u\right),&(r')^2<10^{\ell+1},\\ 10^m\,\Delta\!\left(10^{\ell+1+2t}+u\right),&(r')^2\ge 10^{\ell+1}. \end{cases}$$

The recursion and the final assembly

Let \(F(r,\ell,t)\) be the sum of \(\Delta(n^2)\) over all roots consistent with the state \((r,\ell,t)\). For each prepended digit \(d\), with \(r'=d\,10^\ell+r\), the recursion is

$$F(r,\ell,t)=\sum_{d=0}^{9} \begin{cases} C(r',\ell+1,t),&b<a,\\ F(r',\ell+1,t),&b\ge a, \end{cases}$$

and the base case is

$$F(r,\ell,t)=\Delta\!\left((r\,10^t)^2\right)\qquad\text{when }\ell+t\ge k.$$

Finally, every positive root belongs to exactly one initial state determined by its last nonzero digit and its trailing-zero count, so

$$\sum_{n=1}^{10^k-1}\Delta(n^2)=\sum_{d=1}^{9}\sum_{t=0}^{k-1}F(d,1,t).$$

Worked examples

Start with the branch \(r=3\), \(\ell=1\), \(t=0\). The known square suffix is \(3^2=9\), so \(a=9\). Prepend the digit \(1\): then \(r'=13\) and

$$13^2=169,\qquad 169\bmod 100=69,$$

so \(b=6\). Since \(6<9\), the pivot is fixed at the boundary \(6\mid 9\). Therefore all squares coming from roots ending in \(13\) share the same correction:

$$169\to 196,\qquad 113^2=12769\to 12796,\qquad 213^2=45369\to 45396.$$

In each case the change is \(27\), so the branch can be aggregated immediately.

The padding-zero exception is equally important. The width-two block \(01\) represents a real recursive state. For \(1^2=1\), that left zero is not an actual digit, so there is no larger permutation and \(\Delta(1)=-1\). But \(101^2=10201\) has the same visible suffix \(01\) together with a genuine higher prefix, and its next permutation is \(10210\), giving correction \(9\). This is exactly the split handled by the two cases in \(C(r',\ell+1,t)\).

How the Code Works

Precomputation and the closed-form contribution

The C++, Python, and Java implementations precompute powers of ten both as ordinary integers and modulo \(10^9+7\). They begin the answer with the closed-form square sum \(\frac{N(N-1)(2N-1)}{6}\) for \(N=10^k\), and then add the correction sum produced by the recursion.

Recursive exploration of suffix states

From each initial choice of the last nonzero digit \(d\) and the trailing-zero count \(t\), the implementation prepends digits on the left. At each state it computes the old leftmost known square digit \(a\), tests every extension digit through the new digit \(b\), and applies exactly the mathematical rule above: recurse when \(b\ge a\), collapse the whole branch when \(b<a\).

The aggregation count \(10^m\), the suffix value \(u\), and the padding-zero split are all handled directly from the state parameters. No root in the collapsed block is enumerated individually.

Evaluating the permutation correction itself

Whenever a leaf or an aggregated representative must be evaluated, the implementation converts the relevant number into a digit array, performs the standard next lexicographic permutation on those digits, and reads the result back modulo \(10^9+7\). If no next permutation exists, the contribution is \(-x\) modulo \(10^9+7\), matching the definition of \(\Delta(x)\).

The three languages differ only in how they store large integers. The recursive structure, the suffix tests, and the block-aggregation formulas are the same in all three versions.

Complexity Analysis

Let \(T(k)\) be the number of suffix states that are actually visited before they either recurse further or collapse into a block contribution. The running time is \(O(T(k)\,k)\): each state tries ten prepended digits, and every representative next-permutation evaluation touches at most \(2k\) decimal digits because the square of a \(k\)-digit root has at most \(2k\) digits.

A trivial upper bound is \(T(k)\le 10^k-1\), since without early collapses the search tree would degenerate into root-by-root enumeration. The speedup comes from the many branches where the inequality \(b<a\) appears early, allowing a whole family of \(10^m\) roots to be replaced by one or two representative evaluations. Memory usage is \(O(k)\) for the power tables and recursion depth, plus temporary digit arrays of length at most \(2k\).

Footnotes and References

  1. Project Euler problem page: https://projecteuler.net/problem=925
  2. Lexicographic next permutation: Wikipedia - Permutation, generation in lexicographic order
  3. Lexicographic order: Wikipedia - Lexicographic order
  4. Square pyramidal number: Wikipedia - Square pyramidal number
  5. Positional notation: Wikipedia - Positional notation
  6. Modular arithmetic: Wikipedia - Modular arithmetic

Problem 925 source code

C++

#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <vector>

namespace {

using u64 = std::uint64_t;
using u128 = unsigned __int128;

constexpr u64 kMod = 1'000'000'007ULL;
constexpr u64 kInv6 = 166666668ULL;

u64 add_mod(u64 a, u64 b) {
    a += b;
    if (a >= kMod) a -= kMod;
    return a;
}

u64 sub_mod(u64 a, u64 b) {
    return (a >= b) ? (a - b) : (a + kMod - b);
}

u64 mul_mod(u64 a, u64 b) {
    return static_cast<u64>((static_cast<u128>(a) * b) % kMod);
}

bool next_perm_digits(std::uint8_t* digits, int length) {
    int i = length - 2;
    while (i >= 0 && digits[i] >= digits[i + 1]) --i;
    if (i < 0) return false;
    int j = length - 1;
    while (digits[j] <= digits[i]) --j;
    std::swap(digits[i], digits[j]);
    std::reverse(digits + i + 1, digits + length);
    return true;
}

u64 parse_mod_from_digits(const std::uint8_t* digits, int length) {
    u64 v = 0;
    for (int i = 0; i < length; ++i) {
        v = (v * 10 + digits[i]) % kMod;
    }
    return v;
}

u64 b_diff_mod(u128 n) {
    if (n == 0) return 0;

    u128 x = n;
    std::uint8_t rev[64];
    int length = 0;
    while (x > 0) {
        rev[length++] = static_cast<std::uint8_t>(x % 10);
        x /= 10;
    }

    std::uint8_t digits[64];
    for (int i = 0; i < length; ++i) digits[i] = rev[length - 1 - i];

    const u64 n_mod = static_cast<u64>(n % kMod);
    if (!next_perm_digits(digits, length)) {
        return (n_mod == 0) ? 0 : (kMod - n_mod);
    }

    const u64 nxt_mod = parse_mod_from_digits(digits, length);
    return sub_mod(nxt_mod, n_mod);
}

u64 b_of_square_mod(u64 n) {
    const u128 sq = static_cast<u128>(n) * n;

    std::uint8_t rev[64];
    int length = 0;
    u128 x = sq;
    while (x > 0) {
        rev[length++] = static_cast<std::uint8_t>(x % 10);
        x /= 10;
    }

    if (length == 0) return 0;

    std::uint8_t digits[64];
    for (int i = 0; i < length; ++i) digits[i] = rev[length - 1 - i];
    if (!next_perm_digits(digits, length)) return 0;

    return parse_mod_from_digits(digits, length);
}

u64 brute_sum(u64 n) {
    u64 total = 0;
    for (u64 i = 1; i <= n; ++i) total = add_mod(total, b_of_square_mod(i));
    return total;
}

struct Context {
    int k;
    std::vector<u64> pow10_u64;
    std::vector<u128> pow10_u128;
    std::vector<u64> pow10_mod;
};

u64 monotone_diff(u64 root, int length, int trailing, const Context& ctx) {
    const int limit = ctx.k;
    const u128 p10t = ctx.pow10_u128[trailing];
    const u128 root_t = static_cast<u128>(root) * p10t;

    if (length + trailing >= limit) {
        return b_diff_mod(root_t * root_t);
    }

    const u128 p10t2 = p10t * p10t;
    const u64 p10a = ctx.pow10_u64[length];
    const u64 p10b = 10ULL * p10a;
    const u128 p10c = ctx.pow10_u128[limit - length - trailing - 1];
    const u128 p10d = static_cast<u128>(p10b) * p10t2;

    const u64 msb1 = static_cast<u64>((static_cast<u128>(root) * root) % p10a) / (p10a / 10ULL);

    u64 total = 0;
    for (int d = 0; d <= 9; ++d) {
        const u64 candidate = p10a * static_cast<u64>(d) + root;
        const u128 cand_sq = static_cast<u128>(candidate) * candidate;
        const u64 square = static_cast<u64>(cand_sq % p10b);
        const u128 square_t = static_cast<u128>(square) * p10t2;
        const u64 msb2 = square / p10a;

        if (msb2 < msb1) {
            const u64 diff_hi = b_diff_mod(p10d + square_t);
            if (cand_sq == square) {
                const u64 diff_lo = b_diff_mod(square_t);
                const u64 mul = static_cast<u64>((p10c - 1) % kMod);
                total = add_mod(total, diff_lo);
                total = add_mod(total, mul_mod(mul, diff_hi));
            } else {
                const u64 mul = static_cast<u64>(p10c % kMod);
                total = add_mod(total, mul_mod(mul, diff_hi));
            }
        } else {
            total = add_mod(total, monotone_diff(candidate, length + 1, trailing, ctx));
        }
    }

    return total;
}

u64 solve_925(int k) {
    Context ctx;
    ctx.k = k;
    ctx.pow10_u64.assign(k + 1, 1);
    ctx.pow10_u128.assign(2 * k + 2, 1);
    ctx.pow10_mod.assign(k + 1, 1);

    for (int i = 1; i <= k; ++i) {
        ctx.pow10_u64[i] = ctx.pow10_u64[i - 1] * 10ULL;
        ctx.pow10_mod[i] = mul_mod(ctx.pow10_mod[i - 1], 10ULL);
    }
    for (int i = 1; i <= 2 * k + 1; ++i) {
        ctx.pow10_u128[i] = ctx.pow10_u128[i - 1] * static_cast<u128>(10);
    }

    const u64 n_mod = ctx.pow10_mod[k];
    const u64 n1_mod = (n_mod + kMod - 1) % kMod;
    const u64 two_n1_mod = (2ULL * n_mod + kMod - 1) % kMod;

    u64 total = mul_mod(mul_mod(mul_mod(n_mod, n1_mod), two_n1_mod), kInv6);

    for (int d = 1; d <= 9; ++d) {
        for (int t = 0; t < k; ++t) {
            total = add_mod(total, monotone_diff(static_cast<u64>(d), 1, t, ctx));
        }
    }

    return total;
}

void validate() {
    assert(brute_sum(10) == 270);
    assert(brute_sum(100) == 335316);
    assert(solve_925(1) == 270);
    assert(solve_925(2) == 335316);
    assert(solve_925(6) == 265829902ULL);
}

}  // namespace

int main(int argc, char** argv) {
    int k = 16;
    if (argc > 1) k = std::atoi(argv[1]);
    validate();
    std::cout << solve_925(k) << '\n';
    return 0;
}

Python

def solve():
    MOD = 1000000007
    INV6 = 166666668
    k = 16

    def mul_mod(a, b): return a * b % MOD
    def add_mod(a, b): return (a + b) % MOD
    def sub_mod(a, b): return (a - b) % MOD

    def next_perm(digits):
        n = len(digits); i = n - 2
        while i >= 0 and digits[i] >= digits[i+1]: i -= 1
        if i < 0: return None
        j = n - 1
        while digits[j] <= digits[i]: j -= 1
        d = list(digits); d[i], d[j] = d[j], d[i]
        d[i+1:] = d[i+1:][::-1]
        return d

    def parse_mod(digits):
        v = 0
        for d in digits: v = (v * 10 + d) % MOD
        return v

    def b_diff_mod(n):
        if n == 0: return 0
        digits = []; x = n
        while x > 0: digits.append(x % 10); x //= 10
        digits.reverse()
        nm = n % MOD
        nxt = next_perm(digits)
        if nxt is None: return (MOD - nm) % MOD if nm else 0
        return sub_mod(parse_mod(nxt), nm)

    pow10 = [1]*(k+1)
    for i in range(1, k+1): pow10[i] = pow10[i-1]*10
    pow10_mod = [1]*(k+1)
    for i in range(1, k+1): pow10_mod[i] = pow10_mod[i-1]*10 % MOD

    def monotone_diff(root, length, trailing):
        if length + trailing >= k:
            return b_diff_mod(root * pow10[trailing] * root * pow10[trailing])
        p10a = pow10[length]; p10b = 10*p10a
        p10t = pow10[trailing]; p10t2 = p10t*p10t
        p10c = pow10[k - length - trailing - 1]
        p10d = p10b * p10t2
        msb1 = (root*root % p10a) // (p10a//10)
        total = 0
        for d in range(10):
            cand = p10a*d + root
            cs = cand*cand; sq = cs % p10b
            sq_t = sq * p10t2; msb2 = sq // p10a
            if msb2 < msb1:
                dh = b_diff_mod(p10d + sq_t)
                if cs == sq:
                    dl = b_diff_mod(sq_t)
                    m = (p10c - 1) % MOD
                    total = add_mod(total, dl)
                    total = add_mod(total, mul_mod(m, dh))
                else:
                    m = p10c % MOD
                    total = add_mod(total, mul_mod(m, dh))
            else:
                total = add_mod(total, monotone_diff(cand, length+1, trailing))
        return total

    nm = pow10_mod[k]; n1m = (nm + MOD - 1) % MOD; tn1m = (2*nm + MOD - 1) % MOD
    total = mul_mod(mul_mod(mul_mod(nm, n1m), tn1m), INV6)
    for d in range(1, 10):
        for t in range(k):
            total = add_mod(total, monotone_diff(d, 1, t))
    return str(total)

if __name__ == '__main__':
    print(solve())

Java

import java.math.BigInteger;

public class Euler925 {

    static final long kMod = 1000000007L;
    static final long kInv6 = 166666668L;

    static boolean nextPermDigits(byte[] digits, int length) {
        int i = length - 2;
        while (i >= 0 && digits[i] >= digits[i + 1])
            i--;
        if (i < 0)
            return false;
        int j = length - 1;
        while (digits[j] <= digits[i])
            j--;
        byte temp = digits[i];
        digits[i] = digits[j];
        digits[j] = temp;
        for (int l = i + 1, r = length - 1; l < r; l++, r--) {
            temp = digits[l];
            digits[l] = digits[r];
            digits[r] = temp;
        }
        return true;
    }

    static long parseModFromDigits(byte[] digits, int length) {
        long v = 0;
        for (int i = 0; i < length; ++i) {
            v = (v * 10 + digits[i]) % kMod;
        }
        return v;
    }

    static long bDiffMod(BigInteger n) {
        if (n.equals(BigInteger.ZERO))
            return 0;

        String s = n.toString();
        int length = s.length();
        byte[] digits = new byte[length];
        for (int i = 0; i < length; i++) {
            digits[i] = (byte) (s.charAt(i) - '0');
        }

        long nMod = n.remainder(BigInteger.valueOf(kMod)).longValue();
        if (!nextPermDigits(digits, length)) {
            return nMod == 0 ? 0 : kMod - nMod;
        }

        long nxtMod = parseModFromDigits(digits, length);
        return (nxtMod - nMod + kMod) % kMod;
    }

    static class Context {
        int k;
        BigInteger[] pow10Int;
        long[] pow10Mod;

        Context(int k) {
            this.k = k;
            pow10Int = new BigInteger[2 * k + 2];
            pow10Mod = new long[k + 1];

            pow10Int[0] = BigInteger.ONE;
            for (int i = 1; i <= 2 * k + 1; ++i) {
                pow10Int[i] = pow10Int[i - 1].multiply(BigInteger.TEN);
            }

            pow10Mod[0] = 1;
            for (int i = 1; i <= k; ++i) {
                pow10Mod[i] = (pow10Mod[i - 1] * 10) % kMod;
            }
        }
    }

    static long monotoneDiff(long root, int length, int trailing, Context ctx) {
        int limit = ctx.k;
        BigInteger p10t = ctx.pow10Int[trailing];
        BigInteger rootT = BigInteger.valueOf(root).multiply(p10t);

        if (length + trailing >= limit) {
            return bDiffMod(rootT.multiply(rootT));
        }

        BigInteger p10t2 = p10t.multiply(p10t);
        BigInteger p10a = ctx.pow10Int[length];
        BigInteger p10b = p10a.multiply(BigInteger.TEN);
        BigInteger p10c = ctx.pow10Int[limit - length - trailing - 1];
        BigInteger p10d = p10b.multiply(p10t2);

        BigInteger bigRoot = BigInteger.valueOf(root);
        long msb1 = bigRoot.multiply(bigRoot).remainder(p10a).divide(ctx.pow10Int[length - 1]).longValue();

        long total = 0;
        for (int d = 0; d <= 9; ++d) {
            long candidate = ctx.pow10Int[length].longValue() * d + root;
            BigInteger bigCand = BigInteger.valueOf(candidate);
            BigInteger candSq = bigCand.multiply(bigCand);
            BigInteger square = candSq.remainder(p10b);
            BigInteger squareT = square.multiply(p10t2);
            long msb2 = square.divide(p10a).longValue();

            if (msb2 < msb1) {
                long diffHi = bDiffMod(p10d.add(squareT));
                if (candSq.equals(square)) {
                    long diffLo = bDiffMod(squareT);
                    long mul = p10c.subtract(BigInteger.ONE).remainder(BigInteger.valueOf(kMod)).longValue();
                    if (mul < 0)
                        mul += kMod;
                    total = (total + diffLo) % kMod;
                    total = (total + mul * diffHi) % kMod;
                } else {
                    long mul = p10c.remainder(BigInteger.valueOf(kMod)).longValue();
                    if (mul < 0)
                        mul += kMod;
                    total = (total + mul * diffHi) % kMod;
                }
            } else {
                total = (total + monotoneDiff(candidate, length + 1, trailing, ctx)) % kMod;
            }
        }

        return total;
    }

    public static String solve(int k) {
        Context ctx = new Context(k);
        long nMod = ctx.pow10Mod[k];
        long n1Mod = (nMod + kMod - 1) % kMod;
        long twoN1Mod = (2 * nMod + kMod - 1) % kMod;

        long total = (nMod * n1Mod) % kMod;
        total = (total * twoN1Mod) % kMod;
        total = (total * kInv6) % kMod;

        for (int d = 1; d <= 9; ++d) {
            for (int t = 0; t < k; ++t) {
                total = (total + monotoneDiff(d, 1, t, ctx)) % kMod;
            }
        }

        return Long.toString(total);
    }

    public static void main(String[] args) {
        System.out.println(solve(16));
    }
}