【2020年9月12日普及组】序列

题目描述

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

输入

输入共1行,包含2个用空格隔开的整数N和k。
输出
输出共1行,包含一个整数,表示长度为k的“好序列”的个数对1000000007取模后的结果。

输入

3 2

输出

5

说明

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

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

思路:

F [ i ] [ j ] F[i][j] F[i][j]表示序列长度为 i i i且序列最后一个数 b i = j bi =j bi=j的“好序列”的个数。
F [ i ] [ j ] = ∑ F [ i − 1 ] [ x ] F[i][j]=∑F[i-1][x] F[i][j]=F[i1][x]其中 x x x j j j的约数。
可以先预处理出 1 − n 1-n 1n每个数的约数。

#include
#include
#include
#include
#include
#define ll long long
using namespace std;

int n, m; 
ll f[2020][2020];
int q[2020][2020];

inline void prime()
{
     
	for(register int i=1; i<=2000; ++i)
	{
     
		for(register int j=1; j<=sqrt(i); ++j)
			if(i%j==0)
			{
     
				q[i][0]++;
				q[i][q[i][0]]=j;
				if(i%(i/j)==0&&j!=(i/j))
					q[i][0]++,
					q[i][q[i][0]]=i/j;
			}
	}
}

int main()
{
     
	prime();
	scanf("%d%d", &n, &m);
	for(register int i=1; i<=n; ++i)
		f[1][i]=1;
	for(register int i=2; i<=m; ++i)
	{
     
		for(register int j=1; j<=n; ++j)
		{
     
			for(register int k=1; k<=q[j][0]; ++k)
			    f[i][j]=(f[i][j]+f[i-1][q[j][k]])%1000000007;
		}
	}
	register ll ans=0;
	for(register int i=1; i<=n; ++i)
		ans=(ans+f[m][i])%1000000007;
	printf("%lld", ans);
	return 0;
}

你可能感兴趣的:(题解,DP)