题目链接
题意:给N,M要求构造一个长为M的数组A,每个数不大于N,且A[i]是A[i+1]的因子。
思路:枚举第M个数的值,显然每个质因子可以独立讨论,只需要用每个质因子的数量计算,最后将每个质因子的答案乘起来就行,先预处理dp[i][j]表示长度为i,第i个数为j的非降序列长度,计算复杂度O(T*N*sqrt(N)),加点优化实际跑得更快。
# include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
int dp[2003][13], p[2003], vis[2003], low[2003]={0,1}, s[2003];
void add(int &x, int y){
x += y;
if(x >= mod) x -= mod;
}
int main(){
dp[0][0] = 1;
for(int i=1; i<=2000; ++i){
int sum = 0;
for(int j=0; j<=12; ++j){
add(sum, dp[i-1][j]);
add(dp[i][j], sum);
}
}
for(int i=2; i<=2000; ++i){
if(!vis[i]) p[++p[0]] = i, low[i] = i, s[i] = 1;
for(int j=1,k; j<=p[0]&&(k=i*p[j])<=2000; ++j){
vis[k] = 1;
if(i%p[j] == 0){
low[k] = low[i]*p[j];
s[k] = s[i] + 1;
break;
}
s[k] = 1;
low[k] = p[j];
}
}
int T, n, m;
for(scanf("%d",&T);T;--T){
scanf("%d%d",&n,&m);
int ans = 0;
for(int i=1; i<=n; ++i){
int x = i, tot = 1;
while(x>1){
tot = 1LL*tot*dp[m][s[x]]%mod;
x /= low[x];
}
add(ans, tot);
}
printf("%d\n",ans);
}
return 0;
}