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

public class Euler495 {

    private static final long MOD = 1000000007L;

    private static long power(long base, long exp) {
        long res = 1;
        base %= MOD;
        while (exp > 0) {
            if (exp % 2 == 1)
                res = (res * base) % MOD;
            base = (base * base) % MOD;
            exp /= 2;
        }
        return res;
    }

    private static long modInverse(long n) {
        return power(n, MOD - 2);
    }

    private static long[] factorial = new long[101];
    private static long[] invFactorial = new long[101];

    private static void precomputeFactorials() {
        factorial[0] = 1;
        invFactorial[0] = 1;
        for (int i = 1; i <= 100; i++) {
            factorial[i] = (factorial[i - 1] * i) % MOD;
            invFactorial[i] = modInverse(factorial[i]);
        }
    }

    static class Partition {
        List<Integer> parts;

        Partition(List<Integer> parts) {
            this.parts = parts;
        }
    }

    private static void generatePartitions(int target, int minVal, List<Integer> current, List<Partition> result) {
        if (target == 0) {
            result.add(new Partition(new ArrayList<>(current)));
            return;
        }
        for (int i = minVal; i <= target; i++) {
            current.add(i);
            generatePartitions(target - i, i, current, result);
            current.remove(current.size() - 1);
        }
    }

    private static Map<Integer, Integer> getFactorialExponents(int n) {
        Map<Integer, Integer> exponents = new HashMap<>();
        boolean[] isPrime = new boolean[n + 1];
        for (int i = 2; i <= n; i++)
            isPrime[i] = true;

        for (int p = 2; p <= n; p++) {
            if (isPrime[p]) {
                for (int i = 2 * p; i <= n; i += p)
                    isPrime[i] = false;

                int count = 0;
                long pPow = p;
                while (pPow <= n) {
                    count += n / pPow;
                    pPow *= p;
                }
                exponents.put(p, count);
            }
        }
        return exponents;
    }

    private static long solveW(int nVal, int kVal) throws Exception {
        precomputeFactorials();

        Map<Integer, Integer> rawExponents = getFactorialExponents(nVal);
        Map<Integer, Integer> primeCounts = new HashMap<>();
        int maxExponent = 0;

        for (Map.Entry<Integer, Integer> entry : rawExponents.entrySet()) {
            int exp = entry.getValue();
            primeCounts.put(exp, primeCounts.getOrDefault(exp, 0) + 1);
            if (exp > maxExponent)
                maxExponent = exp;
        }

        List<Partition> partitions = new ArrayList<>();
        generatePartitions(kVal, 1, new ArrayList<>(), partitions);

        int numThreads = Runtime.getRuntime().availableProcessors();
        if (numThreads == 0)
            numThreads = 4;
        ExecutorService executor = Executors.newFixedThreadPool(numThreads);

        int partCount = partitions.size();
        int chunkSize = (partCount + numThreads - 1) / numThreads;
        List<Future<Long>> futures = new ArrayList<>();

        final int finalMaxExponent = maxExponent;

        for (int t = 0; t < numThreads; t++) {
            final int start = t * chunkSize;
            final int end = Math.min(start + chunkSize, partCount);
            if (start >= end)
                continue;

            futures.add(executor.submit(() -> {
                long localSum = 0;
                long[] dp = new long[finalMaxExponent + 1];

                for (int i = start; i < end; i++) {
                    Partition p = partitions.get(i);

                    Map<Integer, Integer> partCounts = new HashMap<>();
                    long termCoeff = 1;

                    for (int val : p.parts) {
                        partCounts.put(val, partCounts.getOrDefault(val, 0) + 1);

                        long invVal = modInverse(val);
                        long sign = ((val - 1) % 2 == 0) ? 1 : -1;
                        long term = (sign * invVal) % MOD;
                        if (term < 0)
                            term += MOD;

                        termCoeff = (termCoeff * term) % MOD;
                    }

                    for (Map.Entry<Integer, Integer> entry : partCounts.entrySet()) {
                        termCoeff = (termCoeff * invFactorial[entry.getValue()]) % MOD;
                    }

                    for (int iDp = 0; iDp <= finalMaxExponent; iDp++)
                        dp[iDp] = 0;
                    dp[0] = 1;

                    for (int val : p.parts) {
                        for (int j = val; j <= finalMaxExponent; j++) {
                            dp[j] = (dp[j] + dp[j - val]);
                            if (dp[j] >= MOD)
                                dp[j] -= MOD;
                        }
                    }

                    long sLambda = 1;
                    for (Map.Entry<Integer, Integer> entry : primeCounts.entrySet()) {
                        long ways = dp[entry.getKey()];
                        if (ways == 0) {
                            sLambda = 0;
                            break;
                        }
                        sLambda = (sLambda * power(ways, entry.getValue())) % MOD;
                    }

                    long totalTerm = (termCoeff * sLambda) % MOD;
                    localSum = (localSum + totalTerm) % MOD;
                }
                return localSum;
            }));
        }

        long totalW = 0;
        for (Future<Long> f : futures) {
            totalW = (totalW + f.get()) % MOD;
        }
        executor.shutdown();
        return totalW;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(solveW(10000, 30));
    }
}
