import java.util.*;

public class Euler636 {
    static final int MOD = 1000000007;
    static final int K = 30;

    static int addmod(int a, int b) {
        int s = a + b;
        if (s >= MOD)
            s -= MOD;
        return s;
    }

    static int submod(int a, int b) {
        int s = a - b;
        if (s < 0)
            s += MOD;
        return s;
    }

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

    static int gcd(int a, int b) {
        while (b != 0) {
            int t = b;
            b = a % b;
            a = t;
        }
        return a;
    }

    static class Entry {
        ArrayList<Integer> sums;
        int weightMod;
        int gcdVal;

        Entry(ArrayList<Integer> sums, int weightMod, int gcdVal) {
            this.sums = sums;
            this.weightMod = weightMod;
            this.gcdVal = gcdVal;
        }
    }

    static ArrayList<Entry> entriesCache = null;

    static ArrayList<Entry> buildEntries() {
        if (entriesCache != null)
            return entriesCache;
        int[] exps = { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
        int n = exps.length;
        long[] fact = new long[11];
        fact[0] = 1;
        for (int i = 1; i <= 10; ++i)
            fact[i] = fact[i - 1] * i;

        HashMap<ArrayList<Integer>, Long> weightMap = new HashMap<>();
        ArrayList<Integer> sums = new ArrayList<>();
        ArrayList<Integer> sizes = new ArrayList<>();

        class Dfs {
            void run(int idx) {
                if (idx == n) {
                    ArrayList<Integer> key = new ArrayList<>(sums);
                    Collections.sort(key);
                    int blocks = sizes.size();
                    long mu = ((n - blocks) % 2 == 0) ? 1 : -1;
                    for (int sz : sizes)
                        mu *= fact[sz - 1];
                    weightMap.put(key, weightMap.getOrDefault(key, 0L) + mu);
                    return;
                }
                for (int i = 0; i < sums.size(); ++i) {
                    sums.set(i, sums.get(i) + exps[idx]);
                    sizes.set(i, sizes.get(i) + 1);
                    run(idx + 1);
                    sizes.set(i, sizes.get(i) - 1);
                    sums.set(i, sums.get(i) - exps[idx]);
                }
                sums.add(exps[idx]);
                sizes.add(1);
                run(idx + 1);
                sums.remove(sums.size() - 1);
                sizes.remove(sizes.size() - 1);
            }
        }
        new Dfs().run(0);

        ArrayList<Entry> entries = new ArrayList<>();
        for (Map.Entry<ArrayList<Integer>, Long> kv : weightMap.entrySet()) {
            long w = kv.getValue();
            if (w == 0)
                continue;
            int g = 0;
            for (int s : kv.getKey())
                g = gcd(g, s);
            int wmod = (int) (w % MOD);
            if (wmod < 0)
                wmod += MOD;
            entries.add(new Entry(kv.getKey(), wmod, g));
        }
        entriesCache = entries;
        return entries;
    }

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

    static class ExpCounts {
        ArrayList<int[]> small = new ArrayList<>();
        ArrayList<int[]> big = new ArrayList<>();
        int maxSmall;
        boolean hasExp1;
    }

    static ExpCounts buildExpCounts(int n) {
        ArrayList<Integer> primes = sievePrimes(n);
        int[] cnt = new int[n + 1];
        for (int p : primes) {
            int e = 0;
            int m = n;
            while (m > 0) {
                m /= p;
                e += m;
            }
            cnt[e]++;
        }

        int maxSmall = Math.max(30, (int) Math.sqrt(n));
        ExpCounts res = new ExpCounts();
        res.maxSmall = maxSmall;
        res.hasExp1 = n >= 2 && cnt[1] > 0;

        for (int e = 1; e <= n; ++e) {
            if (cnt[e] == 0)
                continue;
            if (e <= maxSmall)
                res.small.add(new int[] { e, cnt[e] });
            else
                res.big.add(new int[] { e, cnt[e] });
        }
        return res;
    }

    static int[] combineVecs(int[] a, int[] b, int[] rec) {
        long[] tmp = new long[2 * K];
        for (int i = 0; i < K; ++i) {
            if (a[i] == 0)
                continue;
            for (int j = 0; j < K; ++j) {
                if (b[j] == 0)
                    continue;
                tmp[i + j] = (tmp[i + j] + (long) a[i] * b[j]) % MOD;
            }
        }
        for (int i = 2 * K - 2; i >= K; --i) {
            long val = tmp[i];
            if (val == 0)
                continue;
            for (int j = 1; j <= K; ++j) {
                tmp[i - j] = (tmp[i - j] + val * rec[j - 1]) % MOD;
            }
        }
        int[] res = new int[K];
        for (int i = 0; i < K; ++i)
            res[i] = (int) tmp[i];
        return res;
    }

    static int linearRec(int[] rec, int[] init, int n) {
        if (n < K)
            return init[n];
        int[] pol = new int[K];
        int[] base = new int[K];
        pol[0] = 1;
        base[1] = 1;

        int m = n;
        while (m > 0) {
            if ((m & 1) == 1)
                pol = combineVecs(pol, base, rec);
            base = combineVecs(base, base, rec);
            m >>= 1;
        }

        long ans = 0;
        for (int i = 0; i < K; ++i) {
            ans = (ans + (long) pol[i] * init[i]) % MOD;
        }
        return (int) ans;
    }

    static int computeContribution(Entry entry, ExpCounts counts, int[] dp) {
        Arrays.fill(dp, 0);
        dp[0] = 1;
        for (int s : entry.sums) {
            for (int e = s; e <= counts.maxSmall; ++e) {
                dp[e] = addmod(dp[e], dp[e - s]);
            }
        }

        long res = 1;
        for (int[] pr : counts.small) {
            int val = dp[pr[0]];
            if (val == 0)
                return 0;
            res = (res * modPow(val, pr[1])) % MOD;
        }

        if (counts.big.isEmpty()) {
            return (int) (res * entry.weightMod % MOD);
        }

        int[] C = new int[K + 1];
        C[0] = 1;
        int deg = 0;
        for (int s : entry.sums) {
            for (int i = deg; i >= 0; --i) {
                C[i + s] = submod(C[i + s], C[i]);
            }
            deg += s;
        }

        int[] rec = new int[K];
        for (int i = 1; i <= K; ++i) {
            rec[i - 1] = submod(0, C[i]);
        }

        for (int[] pr : counts.big) {
            int val = linearRec(rec, dp, pr[0]);
            if (val == 0)
                return 0;
            res = (res * modPow(val, pr[1])) % MOD;
        }

        return (int) (res * entry.weightMod % MOD);
    }

    public static String solve() {
        int n = 1000000;
        ExpCounts counts = buildExpCounts(n);
        ArrayList<Entry> entries = buildEntries();

        ArrayList<Integer> active = new ArrayList<>();
        if (counts.hasExp1) {
            for (int i = 0; i < entries.size(); ++i) {
                if (entries.get(i).gcdVal == 1)
                    active.add(i);
            }
        } else {
            for (int i = 0; i < entries.size(); ++i)
                active.add(i);
        }

        if (active.isEmpty())
            return "0";

        int inv288 = modPow(288, MOD - 2);
        int[] dp = new int[counts.maxSmall + 1];
        long total = 0;

        for (int idx : active) {
            total += computeContribution(entries.get(idx), counts, dp);
            if (total >= MOD)
                total -= MOD;
        }

        return Integer.toString((int) (total * inv288 % MOD));
    }

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