【2020.9.12SSL模拟赛T2】序列【DP】

1138.序列

时间限制:1000MS
内存限制:128000KB

题目描述

    一个长度为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 ] [1,1],[1,2],[1,3],[2,2],[3,3] [1,1][1,2][1,3][2,2][3,3]

分析:

D P DP DP
p p p j j j的约数 f [ i ] [ j ] f[i][j] f[i][j]表示前 i i i为确定且末位为 j j j
动态能量转移方程
f [ i + 1 ] [ j ∗ p ] = ( f [ i + 1 ] [ j ∗ p ] + f [ i ] [ j ] ) f[i+1][j*p]=(f[i+1][j*p]+f[i][j]) f[i+1][jp]=(f[i+1][jp]+f[i][j])% 1000000007 1000000007 1000000007
读好题就好了

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#pragma GCC optimize(2)
using namespace std;
const int N=2005;
int n,k,f[N][N],ans;
int main(){
    
    
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		f[1][i]=1;
	for(register int i=1;i<=k;i++)
		for(register int j=1;j<=n;j++)
			for(register int p=1;p<=n/j;p++)  //约数
				f[i+1][j*p]=(f[i+1][j*p]+f[i][j])%1000000007;  //转移
	for(int i=1;i<=n;i++)
		ans=(ans+f[k][i])%1000000007;  //统计
	printf("%d",ans);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/108550875