import java.util.ArrayList;
import java.util.List;

public class Euler546 {
    static final long MOD = 1000000007L;

    static long modPow(long base, long exp) {
        long res = 1 % MOD;
        long cur = base % MOD;
        while (exp > 0) {
            if ((exp & 1) != 0)
                res = (res * cur) % MOD;
            cur = (cur * cur) % MOD;
            exp >>= 1;
        }
        return res;
    }

    static class Precomputed {
        int maxDeg;
        long[][] binom;
        long[][] sumPow;

        Precomputed(int maxDeg, long[][] binom, long[][] sumPow) {
            this.maxDeg = maxDeg;
            this.binom = binom;
            this.sumPow = sumPow;
        }
    }

    static List<Integer> toDigits(long n, int base) {
        if (n == 0) {
            List<Integer> list = new ArrayList<>();
            list.add(0);
            return list;
        }
        List<Integer> digits = new ArrayList<>();
        while (n > 0) {
            digits.add((int) (n % base));
            n /= base;
        }
        return digits;
    }

    static Precomputed buildPrecomputed(int maxDeg) {
        int size = maxDeg + 2;
        long[][] binom = new long[size][size];
        for (int n = 0; n < size; n++) {
            binom[n][0] = 1;
            binom[n][n] = 1;
            for (int k = 1; k < n; k++) {
                binom[n][k] = (binom[n - 1][k - 1] + binom[n - 1][k]) % MOD;
            }
        }

        long[][] stirling = new long[size][size];
        stirling[0][0] = 1;
        for (int n = 1; n < size; n++) {
            for (int k = 1; k <= n; k++) {
                stirling[n][k] = (stirling[n - 1][k - 1] + (long) k * stirling[n - 1][k]) % MOD;
            }
        }

        long[] fact = new long[size + 1];
        fact[0] = 1;
        for (int i = 1; i < fact.length; i++) {
            fact[i] = (fact[i - 1] * i) % MOD;
        }

        long[][] polyBinom = new long[size][];
        polyBinom[0] = new long[] { 1 };
        for (int m = 1; m < size; m++) {
            long[] prev = polyBinom[m - 1];
            long[] cur = new long[prev.length + 1];
            for (int p = 0; p < prev.length; p++) {
                long a = prev[p];
                long dec = (a * (m - 1)) % MOD;
                cur[p] = (cur[p] - dec + MOD) % MOD;
                cur[p + 1] = (cur[p + 1] + a) % MOD;
            }
            long invM = modPow(m, MOD - 2);
            for (int i = 0; i < cur.length; i++) {
                cur[i] = (cur[i] * invM) % MOD;
            }
            polyBinom[m] = cur;
        }

        long[][] polyBinomShift = new long[size][];
        for (int m = 0; m < size; m++) {
            long[] poly = polyBinom[m];
            long[] shift = new long[poly.length];
            for (int p = 0; p < poly.length; p++) {
                long a = poly[p];
                if (a == 0)
                    continue;
                for (int q = 0; q <= p; q++) {
                    long add = (a * binom[p][q]) % MOD;
                    shift[q] = (shift[q] + add) % MOD;
                }
            }
            polyBinomShift[m] = shift;
        }

        long[][] sumPow = new long[maxDeg + 1][];
        for (int p = 0; p <= maxDeg; p++) {
            long[] poly = new long[p + 2];
            for (int j = 0; j <= p; j++) {
                if (stirling[p][j] == 0)
                    continue;
                long coeff = (stirling[p][j] * fact[j]) % MOD;
                long[] baseArr = polyBinomShift[j + 1];
                for (int idx = 0; idx < baseArr.length; idx++) {
                    long add = (coeff * baseArr[idx]) % MOD;
                    poly[idx] = (poly[idx] + add) % MOD;
                }
            }
            sumPow[p] = poly;
        }

        return new Precomputed(maxDeg, binom, sumPow);
    }

    static long[] prefixSumPoly(long[] poly, Precomputed pre) {
        long[] res = new long[poly.length + 1];
        for (int p = 0; p < poly.length; p++) {
            long a = poly[p];
            if (a == 0)
                continue;
            long[] base = pre.sumPow[p];
            for (int i = 0; i < base.length; i++) {
                long add = (a * base[i]) % MOD;
                res[i] = (res[i] + add) % MOD;
            }
        }
        return res;
    }

    static long[] substitutePoly(long[] poly, int k, int s, Precomputed pre, long[] powK) {
        int d = poly.length - 1;
        long[] powS = new long[d + 1];
        powS[0] = 1;
        for (int i = 1; i <= d; i++) {
            powS[i] = (powS[i - 1] * s) % MOD;
        }

        long[] res = new long[d + 1];
        for (int p = 0; p <= d; p++) {
            long a = poly[p];
            if (a == 0)
                continue;
            for (int q = 0; q <= p; q++) {
                long term = (a * pre.binom[p][q]) % MOD;
                term = (term * powK[q]) % MOD;
                term = (term * powS[p - q]) % MOD;
                res[q] = (res[q] + term) % MOD;
            }
        }
        return res;
    }

    static long computeF(long n, int k, Precomputed pre) {
        if (n == 0)
            return 1;
        List<Integer> digits = toDigits(n, k);
        int L = digits.size() - 1;

        long[] powK = new long[pre.maxDeg + 2];
        powK[0] = 1;
        for (int i = 1; i < powK.length; i++) {
            powK[i] = (powK[i - 1] * k) % MOD;
        }

        long[] freePoly = { k % MOD };
        long[] tightPoly = { (digits.get(0) + 1) % MOD };
        if (L == 0)
            return tightPoly[0];

        for (int j = 1; j <= L; j++) {
            long[] sumFree = prefixSumPoly(freePoly, pre);
            long[] sumTight = prefixSumPoly(tightPoly, pre);

            long[] newFree = new long[sumFree.length];
            for (int s = 0; s < k; s++) {
                long[] sub = substitutePoly(sumFree, k, s, pre, powK);
                for (int i = 0; i < sub.length; i++) {
                    newFree[i] = (newFree[i] + sub[i]) % MOD;
                }
            }

            long[] newTight = new long[sumFree.length];
            int dj = digits.get(j);
            for (int s = 0; s < dj; s++) {
                long[] sub = substitutePoly(sumFree, k, s, pre, powK);
                for (int i = 0; i < sub.length; i++) {
                    newTight[i] = (newTight[i] + sub[i]) % MOD;
                }
            }
            long[] subTight = substitutePoly(sumTight, k, dj, pre, powK);
            for (int i = 0; i < subTight.length; i++) {
                newTight[i] = (newTight[i] + subTight[i]) % MOD;
            }

            freePoly = newFree;
            tightPoly = newTight;
        }

        return tightPoly[0] % MOD;
    }

    public static String solve() {
        long n = 100000000000000L;
        long maxN = Math.max(n, 1000L);
        int maxDeg = toDigits(maxN, 2).size() + 2;
        Precomputed pre = buildPrecomputed(maxDeg);

        long total = 0;
        for (int k = 2; k <= 10; k++) {
            long val = computeF(n, k, pre);
            total = (total + val) % MOD;
        }
        return Long.toString(total);
    }

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