考虑设 (dp_{i,j}) 表示已经确定了前 (i) 个数,且最后一个数是 (j) 的方案数。
转移很容易想到:
- 设 (v_j) 表示 (j) 的所有约数的集合,那么就有 (dp_{i,j}=sumlimits_{kin v_j}dp_{i-1,k})。
预处理出 (v_j),然后直接转移即可。
#include <bits/stdc++.h>
using namespace std;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}
const int INF = 0x3f3f3f3f, N = 2003, M = N << 1, mod = 1000000007;
int n, m;
int dp[N][N];
vector <int> v[N];
int main()
{
n = gi(), m = gi();
for (int i = 1; i <= n; i+=1)
for (int j = 1; j * j <= i; j+=1)
if (i % j == 0)
{
v[i].push_back(j);
if (j * j != i) v[i].push_back(i / j);
}
dp[0][1] = 1;
for (int i = 1; i <= m; i+=1)
for (int j = 1; j <= n; j+=1)
{
for (auto x : v[j])
(dp[i][j] += dp[i - 1][x]) %= mod;
}
int ans = 0;
for (int i = 1; i <= n; i+=1)
(ans += dp[m][i]) %= mod;
printf("%d
", ans);
return 0;
}