import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;

public class Euler715 {
    static final long kMod = 1000000007L;

    static long modNorm(long x) {
        x %= kMod;
        if (x < 0)
            x += kMod;
        return x;
    }

    static long modAdd(long a, long b) {
        long s = a + b;
        if (s >= kMod)
            s -= kMod;
        return s;
    }

    static long modMul(long a, long b) {
        return (a * b) % kMod;
    }

    static int[] sievePrimes(int n) {
        byte[] isPrime = new byte[n + 1];
        Arrays.fill(isPrime, (byte) 1);
        if (n >= 0)
            isPrime[0] = 0;
        if (n >= 1)
            isPrime[1] = 0;

        for (int i = 2; (long) i * i <= n; ++i) {
            if (isPrime[i] != 0) {
                for (int j = i * i; j <= n; j += i) {
                    isPrime[j] = 0;
                }
            }
        }

        int count = 0;
        for (int i = 2; i <= n; ++i) {
            if (isPrime[i] != 0)
                count++;
        }

        int[] primes = new int[count];
        int idx = 0;
        for (int i = 2; i <= n; ++i) {
            if (isPrime[i] != 0)
                primes[idx++] = i;
        }
        return primes;
    }

    static class Pair<T, U> {
        T first;
        U second;

        Pair(T first, U second) {
            this.first = first;
            this.second = second;
        }
    }

    static Pair<long[], long[]> sumPrimeCubes(long n, int L, int XL, int[] primes) {
        long[] V = new long[XL];
        long s = -1;
        for (int i = 1; i < XL; ++i) {
            long ii = i % kMod;
            s = modNorm(s + modMul(modMul(ii, ii), ii));
            V[i] = s;
        }

        long[] bigV = new long[L + 1];
        long mod2 = kMod * 2L;
        for (int i = 1; i <= L; ++i) {
            long x = (n / i) % mod2;
            long y = (x * (x + 1L) % mod2) / 2L;
            bigV[i] = modNorm(modMul(y % kMod, y % kMod) - 1);
        }

        for (int p : primes) {
            long sp = V[p - 1];
            long pSq = (long) p * p;
            long pMod = p % kMod;
            long p3 = modMul(pMod, modMul(pMod, pMod));
            long y = n / p;
            int iL = (int) Math.min(y / p, L);

            for (int i = 1; i <= iL; ++i) {
                long z = y / i;
                long v = (z < XL) ? V[(int) z] : bigV[i * p];
                bigV[i] = modNorm(bigV[i] - modMul(p3, modNorm(v - sp)));
            }

            for (int x = XL - 1; x > 0; --x) {
                if (x < pSq)
                    break;
                int z = x / p;
                V[x] = modNorm(V[x] - modMul(p3, modNorm(V[z] - sp)));
            }
        }

        return new Pair<>(V, bigV);
    }

    static Pair<long[], long[]> primeBalanceMod4(long n, int L, int XL, int[] primes) {
        long[] V = new long[XL];
        for (int i = 3; i < XL; i += 4)
            V[i] = -1;
        for (int i = 4; i < XL; i += 4)
            V[i] = -1;

        long[] bigV = new long[L + 1];
        for (int i = 1; i <= L; ++i) {
            if (((n / i - 1) % 4) >= 2)
                bigV[i] = -1;
        }

        for (int p : primes) {
            long sp = V[p - 1];
            long y = n / p;
            int iL = (int) Math.min(y / p, L);
            long f = 2 - (p % 4);

            for (int i = 1; i <= iL; ++i) {
                long z = y / i;
                if (z < XL) {
                    bigV[i] -= f * (V[(int) z] - sp);
                } else {
                    bigV[i] -= f * (bigV[i * p] - sp);
                }
            }

            long pSq = (long) p * p;
            for (int x = XL - 1; x > 0; --x) {
                if (x < pSq)
                    break;
                int z = x / p;
                V[x] -= f * (V[z] - sp);
            }
        }

        return new Pair<>(V, bigV);
    }

    static class DfsContext {
        int[] primes;
        long[] p2;
        long[] p3;
        int L;
        long[] V;
        long[] bigV;

        long dfsBranch(int i, long n0, long x0) {
            long pSq = p2[i];
            if (n0 < pSq)
                return 0;

            long p = primes[i];
            long pCubed = p3[i];
            long n = n0 / p;
            long x = x0 * p;
            long f = modNorm(pCubed + (p % 4) - 2);
            long res = 0;

            long pref = (x <= L) ? bigV[(int) x] : V[(int) n];
            res = modAdd(res, modMul(f, modNorm(pref - V[(int) p])));

            while (true) {
                if (n > pSq) {
                    res = modAdd(res, modMul(f, dfs(i + 1, n, x)));
                }
                n /= p;
                if (n == 0)
                    break;

                x *= p;
                f = modMul(f, pCubed);
                res = modAdd(res, f);

                if (n > p) {
                    long pref2 = (x <= L) ? bigV[(int) x] : V[(int) n];
                    res = modAdd(res, modMul(f, modNorm(pref2 - V[(int) p])));
                }
            }
            return res;
        }

        long dfs(int i0, long n0, long x0) {
            long res = 0;
            for (int i = i0; i < primes.length; ++i) {
                if (n0 < p2[i])
                    break;
                res = modAdd(res, dfsBranch(i, n0, x0));
            }
            return res;
        }
    }

    public static String solve() {
        long n = 1000000000000L;
        int L = (int) Math.sqrt(n + 0.5);
        int XL = (int) (n / L) + 1;
        int[] primes = sievePrimes(L);

        Pair<long[], long[]> res1 = sumPrimeCubes(n, L, XL, primes);
        long[] V1 = res1.first;
        long[] bigV1 = res1.second;

        Pair<long[], long[]> res2 = primeBalanceMod4(n, L, XL, primes);
        long[] V2 = res2.first;
        long[] bigV2 = res2.second;

        long[] V = new long[XL];
        for (int i = 0; i < XL; ++i) {
            V[i] = modNorm(V1[i] - modNorm(V2[i]));
        }

        long[] bigV = new long[L + 1];
        for (int i = 0; i <= L; ++i) {
            bigV[i] = modNorm(bigV1[i] - modNorm(bigV2[i]));
        }

        long[] p2 = new long[primes.length];
        long[] p3 = new long[primes.length];
        for (int i = 0; i < primes.length; ++i) {
            long p = primes[i];
            p2[i] = p * p;
            long pMod = p % kMod;
            p3[i] = modMul(pMod, modMul(pMod, pMod));
        }

        DfsContext ctx = new DfsContext();
        ctx.primes = primes;
        ctx.p2 = p2;
        ctx.p3 = p3;
        ctx.L = L;
        ctx.V = V;
        ctx.bigV = bigV;

        int rootEnd = 0;
        while (rootEnd < primes.length && p2[rootEnd] <= n) {
            rootEnd++;
        }

        if (rootEnd == 0) {
            return Long.toString(modNorm(1 + bigV[1]));
        }

        int threads = Runtime.getRuntime().availableProcessors();
        threads = Math.min(threads, rootEnd);

        ExecutorService executor = Executors.newFixedThreadPool(threads);
        List<Future<Long>> futures = new ArrayList<>();

        for (int i = 0; i < rootEnd; i++) {
            final int branchI = i;
            futures.add(executor.submit(() -> ctx.dfsBranch(branchI, n, 1L)));
        }

        long dfsTotal = 0;
        try {
            for (Future<Long> f : futures) {
                dfsTotal = modAdd(dfsTotal, f.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        executor.shutdown();

        return Long.toString(modNorm(1 + bigV[1] + dfsTotal));
    }

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