第六周Mashmokh and ACM(Dp Y)

Mashmokh’s boss, Bimokh, didn’t like Mashmokh. So he fired him. Mashmokh decided to go to university and participate in ACM instead of finding a new job. He wants to become a member of Bamokh’s team. In order to join he was given some programming tasks and one week to solve them. Mashmokh is not a very experienced programmer. Actually he is not a programmer at all. So he wasn’t able to solve them. That’s why he asked you to help him with these tasks. One of these tasks is the following.

A sequence of l integers b1, b2, …, bl (1 ≤ b1 ≤ b2 ≤ … ≤ bl ≤ n) is called good if each number divides (without a remainder) by the next number in the sequence. More formally for all i (1 ≤ i ≤ l - 1).

Given n and k find the number of good sequences of length k. As the answer can be rather large print it modulo 1000000007 (109 + 7).

Input
The first line of input contains two space-separated integers n, k (1 ≤ n, k ≤ 2000).

Output
Output a single integer — the number of good sequences of length k modulo 1000000007 (109 + 7).
Input
3 2
Output
5
Input
6 4
Output
39
Input
2 1
Output
2
Note
In the first sample the good sequences are: [1, 1], [2, 2], [3, 3], [1, 2], [1, 3].

题意:n表示序列长,在其中找长度为K的一个数能被上一个数整除的好序列个数。

考虑:以该位置元素为结尾,该位置的状态是指前一个位置元素结尾的长度为k的好序列数加上该位置与之前元素组成的长度为k的好序列数。

有三个要注意的点并且要将它们联系在一起。
长度k。整除。结尾。
回答:遍历序列,以每个元素为结尾,找其倍数,加到下一长度元素为该元素倍数的状态值上(状态值为以该元素为结尾好序列的个数)。这样的话也可以将视角转化到该长度,则该长度是由上一长度该元素的因子状态值累加而成。

长度k为i大循环,遍历长度为n的序列,当遍历到元素j时,用另一个循环p来找到j的倍数,即能整除j的元素,将以j为结尾的长度i-1的状态值加到以j的倍数为结尾的长度为i+1的状态上。即以j为定位将其上一长度的值加到所有j的倍数这一长度的状态值上,这样长度为0到k所有的都被上一长度以每个序列元素为结尾,找到它的个数将其状态值添加到该长度元素倍数上,像n=5,k=4,以j=2元素为结尾,它的倍数有2,4,将dp[i][2]分别加到dp[i+1][2],dp[i+1][4]上,当然该序列够长,2或4还会是其他元素的倍数,像j=4,
那么其状态值dp[i][4]还会添加到dp[i+1][4]上。概括一下就是该长度的与上一长度的有关,并且上一长度数组所有该元素的因子,会影响到该元素。

以上是我的解题思考,还可参考以下博主的清晰解析。
https://blog.csdn.net/qq_51392086/article/details/115774113?utm_source=app&app_version=4.5.8

https://blog.csdn.net/weixin_51443397/article/details/115798041?utm_source=app&app_version=4.5.8

#include <iostream>
using namespace std;
const int mod=1e9+7;
int dp[2005][2005];
int main() 
{
    int n,k;
    cin>>n>>k;
    dp[0][1]=1;
    for (int i=0;i<=k;i++) 
    {
        for (int j=1;j<=n;j++) 
        {
            for (int t=j; t<=n; t+=j) //找j的倍数
            {
                dp[i+1][t]=(dp[i+1][t]+dp[i][j])%mod;
            }
        }
    }
    int sum=0;
    for (int i = 1; i <= n; i++) //将所有情况相加
    {
        sum=(sum+dp[k][i])%mod;
    }
    cout <<sum<< endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值