版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/83181055
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4011
思路:
dp状态:dp 【数列长度】【数列最尾的那个数】
那么可以得出这个递推公式 : dp【当前数列长度】【数列最尾的数】 = (dp【当前数列长度-1】【比当前数列尾数小或者等于,而且是当前尾数的倍数】的总和),从逻辑分析来看是合理的;因为数字可以重复取,比如m = 3 可以是 111,所以尾数可以等于当前的尾数;为什么dp公式这样写? 如果要整体考虑的话,会非常麻烦,但如果我们一个一个数的添加到数列里面,数列长度从1不断增加到 m,最后得出的就是我们要的结果;比如 n = 5, 我们要找出 m = 3, 尾数是 4的话,长度为2的数列有 1, 2; 2, 4 ; 我们这里暂时不考虑重复的(1,1; 2,2 类似这种) 那么只需要在1,2的后面加个 4; 2,4 后面加个 4,那么就得到 1,2,4; 2,4,4; 这样就有了2个符合题意的数列了;
对应数的倍数可以预先打表;然后要用的时候直接拿出来用就行了
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<sstream>
#include<vector>
#include<string>
#include<set>
using namespace std;
//using namespace __gnu_pbds;
//------------------ 宏定义 --------------------------------
#define IOS ios::sync_with_stdio(false); cin.tie(0);
#define REP(i,n) for(int i=0;i<n;++i)
//------------------- 预备函数 ------------------------------
int read(){
int r=0,f=1;char p=getchar();
while(p>'9'||p<'0'){if(p=='-')f=-1;p=getchar();}
while(p>='0'&&p<='9'){r=r*10+p-48;p=getchar();}return r*f;
}
int dcmp (double x, double y) {
if (fabs(x-y) < 1e-6) return 0;
if (x > y) return 1; return -1;
}
//------------------- 常量+声明 ------------------------------------------
//typedef tree<pair<long long,int>,null_type,less< pair<long long,int> >,rb_tree_tag,tree_order_statistics_node_update> rbtree;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
const int Maxn = 2e3+10;
const long long LINF = 1e18;
const int INF = 0x3f3f3f3f;
const int Mod = 1e9+7;
const double PI = acos(-1.0);
const double esp = 1e-6;
//-------------------------------------------------------------------------
int dp[Maxn][Maxn];
vector <int> a[Maxn];
int main (void)
{ // a存储的是小于或者等于j,能整除j的数
for (int i = 1; i <= 2000; ++i) {
for (int j = i; j <= 2000; j+=i) a[j].push_back (i);
}
int t, n ,m;
scanf ("%d", &t);
while (t--) {
scanf ("%d%d", &n, &m);
memset (dp, 0, sizeof (dp));
dp[0][1] = 1;
int ans = 0;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
int len = a[j].size();
for (int k = 0; k < len; ++k) {
dp[i][j] = (dp[i][j] + dp[i-1][a[j][k]]) % Mod;
}
if (i == m) ans = (ans + dp[i][j]) % Mod;
}
}
printf ("%d\n", ans);
}
return 0;
}