【DP】序列 题解

【DP】序列 题解

序列

题目

一个长度为 k k k的整数序列 b b b 1, b b b 2,…, b k bk bk(1≤ b b b 1≤ b b b 2≤…≤ b k bk bk N N N)称为“好序列”当且仅当后一个数是前一个数的倍数,即 b i bi bi+1是 b i bi bi的倍数对任意的i(1≤ i i i k k k-1)成立。
给定 N N N k k k,请算出有多少个长度为4、 k k k的“好序列”,答案对1000000007取模。


输入

输入共1行,包含2个用空格隔开的整数 N N N k k k


输出

输出共1行,包含一个整数,表示长度为 k k k的“好序列”的个数对1000000007取模后的结果。


样例

input
3 2

output
5


说明

【输入输出样例说明】
“好序列”为:[1,1],[1,2],[1,3],[2,2],[3,3]。

【数据说明】
对于40%的数据,1≤ N N N≤30,1≤ k k k≤10。
对于100%的数据,1≤ N N N≤2000,1≤ k k k≤2000。


解题思路

f[i][j]表示长度为i,以j为最后一个数的“好序列”个数
动态转移方程:
枚举 i i i j j j,以及 j j j的倍数 k k k* j j j
f [ i + 1 ] [ k ∗ j ] = ( f [ i + 1 ] [ k ∗ j ] + f [ i ] [ j ] ) f[i+1][k*j]=(f[i+1][k*j]+f[i][j]) f[i+1][kj]=(f[i+1][kj]+f[i][j])%1000000007;


代码

#include
#include
using namespace std;
int n,m;
long long f[2100][2100],ans;
int main()
{
     
	scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        f[1][i]=1;  //赋初值
    for (int i=1;i<m;i++)  //枚举前一个状态的长度
    {
     
    	for (int j=n;j>0;j--)  //枚举前一个状态的最后一个数
    	    for (int k=1;k*j<=n;k++)  //枚举下一个状态最后一个数是前一个状态的几倍
    	        f[i+1][k*j]=(f[i+1][k*j]+f[i][j])%1000000007;  //转移
    	
	}
	for (int i=1;i<=n;i++)
    	ans=(ans+f[m][i])%1000000007;  //累加这个长度下,最后一个数小于等于n的个数
    printf("%lld",ans);
    return 0;
}

你可能感兴趣的:(动态规划)