import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

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

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

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

    static ArrayList<Integer> primesUpTo(int n) {
        boolean[] isPrime = new boolean[n + 1];
        java.util.Arrays.fill(isPrime, true);
        isPrime[0] = isPrime[1] = false;
        for (int p = 2; p * p <= n; ++p) {
            if (!isPrime[p])
                continue;
            for (int q = p * p; q <= n; q += p) {
                isPrime[q] = false;
            }
        }
        ArrayList<Integer> primes = new ArrayList<>();
        for (int i = 2; i <= n; ++i) {
            if (isPrime[i])
                primes.add(i);
        }
        return primes;
    }

    static class Pair implements Comparable<Pair> {
        int val;
        int idx;

        Pair(int val, int idx) {
            this.val = val;
            this.idx = idx;
        }

        @Override
        public int compareTo(Pair o) {
            return Integer.compare(this.val, o.val);
        }
    }

    static class Engine {
        int N;
        ArrayList<Integer> smallPrimes = new ArrayList<>();
        ArrayList<Integer> largePrimes = new ArrayList<>();
        int[] maxExp;
        int[] radix;
        int[] stride;
        int states = 1;
        long[][] pPow;
        ArrayList<Pair> smallNumbers = new ArrayList<>();

        Engine(int n) {
            this.N = n;
            ArrayList<Integer> primes = primesUpTo(n);
            int root = 1;
            while ((root + 1) * (root + 1) <= n)
                root++;

            for (int p : primes) {
                if (p <= root)
                    smallPrimes.add(p);
                else
                    largePrimes.add(p);
            }

            int k = smallPrimes.size();
            maxExp = new int[k];
            radix = new int[k];

            for (int i = 0; i < k; ++i) {
                int p = smallPrimes.get(i);
                int e = 0;
                long v = 1;
                while (v * p <= N) {
                    v *= p;
                    e++;
                }
                maxExp[i] = e;
                radix[i] = e + 1;
                states *= radix[i];
            }

            stride = new int[k];
            if (k > 0)
                stride[k - 1] = 1;
            for (int i = k - 2; i >= 0; --i) {
                stride[i] = stride[i + 1] * radix[i + 1];
            }

            pPow = new long[k][];
            for (int i = 0; i < k; ++i) {
                int emax = maxExp[i];
                pPow[i] = new long[emax + 1];
                pPow[i][0] = 1;
                for (int e = 1; e <= emax; ++e) {
                    pPow[i][e] = modMul(pPow[i][e - 1], smallPrimes.get(i));
                }
            }

            genSmallNumbers(0, 1, 0);
            Collections.sort(smallNumbers);
        }

        void genSmallNumbers(int i, long value, int idx) {
            if (i == smallPrimes.size()) {
                smallNumbers.add(new Pair((int) value, idx));
                return;
            }

            long v = value;
            int p = smallPrimes.get(i);
            int baseIdx = idx * radix[i];
            for (int e = 0; e <= maxExp[i]; ++e) {
                genSmallNumbers(i + 1, v, baseIdx + e);
                if (e == maxExp[i])
                    break;
                if (v > N / p)
                    break;
                v *= p;
            }
        }

        void prefixTransform(int[] arr) {
            int k = smallPrimes.size();
            for (int d = 0; d < k; ++d) {
                int st = stride[d];
                int block = radix[d] * st;
                for (int base = 0; base < states; base += block) {
                    for (int off = 0; off < st; ++off) {
                        int idx = base + off;
                        for (int e = 1; e < radix[d]; ++e) {
                            idx += st;
                            arr[idx] += arr[idx - st];
                        }
                    }
                }
            }
        }

        short[] countsForLimit(int limit) {
            int[] arr = new int[states];
            for (Pair p : smallNumbers) {
                if (p.val > limit)
                    break;
                arr[p.idx] = 1;
            }
            prefixTransform(arr);

            short[] out = new short[states];
            for (int i = 0; i < states; ++i)
                out[i] = (short) arr[i];
            return out;
        }

        long solveMod() {
            ArrayList<Integer> neededLimitsList = new ArrayList<>();
            neededLimitsList.add(N);

            HashMap<Integer, ArrayList<Integer>> groups = new HashMap<>();
            for (int p : largePrimes) {
                int l = N / p;
                groups.computeIfAbsent(l, k -> new ArrayList<>()).add(p);
            }
            neededLimitsList.addAll(groups.keySet());

            Collections.sort(neededLimitsList);
            ArrayList<Integer> neededLimits = new ArrayList<>();
            if (!neededLimitsList.isEmpty()) {
                neededLimits.add(neededLimitsList.get(0));
                for (int i = 1; i < neededLimitsList.size(); ++i) {
                    if (!neededLimitsList.get(i).equals(neededLimitsList.get(i - 1))) {
                        neededLimits.add(neededLimitsList.get(i));
                    }
                }
            }

            HashMap<Integer, short[]> counts = new HashMap<>();
            for (int l : neededLimits) {
                counts.put(l, countsForLimit(l));
            }

            long[] pow2 = new long[N + 1];
            pow2[0] = 1;
            for (int i = 1; i <= N; ++i)
                pow2[i] = (pow2[i - 1] * 2) % MOD;

            HashMap<Integer, long[]> groupValue = new HashMap<>();
            for (java.util.Map.Entry<Integer, ArrayList<Integer>> entry : groups.entrySet()) {
                int l = entry.getKey();
                ArrayList<Integer> primes = entry.getValue();
                long[] table = new long[N + 1];
                for (int t = 0; t <= N; ++t) {
                    long v = 1;
                    for (int p : primes) {
                        long term = modNorm(1 - p + modMul(p, pow2[t]));
                        v = modMul(v, term);
                    }
                    table[t] = v;
                }
                groupValue.put(l, table);
            }

            long ans = 0;
            int k = smallPrimes.size();

            for (int idx = 0; idx < states; ++idx) {
                int x = idx;
                long d = 1;
                long cut = 1;

                for (int i = k - 1; i >= 0; --i) {
                    int e = x % radix[i];
                    x /= radix[i];

                    d = modMul(d, pPow[i][e]);
                    if (e < maxExp[i]) {
                        cut = modMul(cut, modNorm(1 - smallPrimes.get(i)));
                    }
                }

                long term = modMul(d, cut);
                int t0 = counts.get(N)[idx];
                term = modMul(term, pow2[t0]);

                for (java.util.Map.Entry<Integer, long[]> entry : groupValue.entrySet()) {
                    int l = entry.getKey();
                    long[] table = entry.getValue();
                    int t = counts.get(l)[idx];
                    term = modMul(term, table[t]);
                }

                ans += term;
                if (ans >= MOD)
                    ans -= MOD;
            }

            return ans;
        }
    }

    public static String solve() {
        Engine e = new Engine(800);
        return Long.toString(e.solveMod());
    }

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