Problem:
M: プレゼント (Presents)

白羽さんは、とある悪魔にサプライズプレゼントとして次のような集合を用意した。

$N$ 以下の異なる $K$ 個の自然数からなる

どの 2 つの値の組を集合から選んでも、片方の数がもう片方の数で割り切れる

実はこのような集合には悪魔の力を奪う性質があり、このままだと力を失ってしまう。

悪魔を助けるために、このような集合がいくつあるか計算せよ。

入力

2 つの整数 $N, K$ が空白区切りで与えられる。

出力

条件を満たす集合の個数を出力せよ。

制約

$N$ は $1$ 以上 $100 \ 000$ 以下の整数

$K$ は $1$ 以上 $N$ 以下の整数

入力例1

6 3

出力例1

3

集合 $(1,2,4), (1,2,6), (1,3,6)$ が条件を満たす。

入力例2

100000 7

出力例2

58848855

$N = 100 \ 000, K = 7$ のとき、条件を満たす集合は $58 \ 848 \ 855$ 通りある。

Solution in JAVA (judge verdict: Accepted)

import java.util.*;

public class Main {
    static HashMap<Integer, HashMap<Integer, Long>> dp = new HashMap<>();
     public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        long total = 0;
        for (int i = 1; i * Math.pow(2, k - 1) <= n; i++) {
            total += search(i, k - 1, n);
        } 
        System.out.println(total);
    }
    
    static long search(int num, int count, int max) {
        if (count == 0) {
            return 1;
        }
        if (dp.containsKey(num)) {
            if (dp.get(num).containsKey(count)) {
                return dp.get(num).get(count);
            }
        }
        long total = 0;
        for (int i = 2; num * i * Math.pow(2, count - 1) <= max; i++) {
            total += search(num * i, count - 1, max);
        }
        if (dp.containsKey(num)) {
            dp.get(num).put(count, total);
        } else {
            HashMap<Integer, Long> map = new HashMap<>();
            map.put(count, total);
            dp.put(num, map);
        }
        return total;
    }
}