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).
The first line of input contains two space-separated integers n, k (1 ≤ n, k ≤ 2000).
Output a single integer — the number of good sequences of length k modulo 1000000007 (109 + 7).
3 2
5
6 4
39
2 1
2
In the first sample the good sequences are: [1, 1], [2, 2], [3, 3], [1, 2], [1, 3].
题目大意:
给你两个数N,K,让你找有多少种合法的序列,使得序列中元素是从1-N的,并且长度为K。
一个序列由:a1,a2,a3.........ak组成,其中需要满足这样一个要求:ai+1%ai==0;
思路:
1、经典的计数问题,设定dp【i】【j】表示长度为i的序列,其最后一个数字为j的可行方案数。
那么不难推出其状态转移方程:
dp【i】【j】=dp【i】【j】+dp【i-1】【k】(其中要求j%k==0),那么如果我们暴力求解:一层for枚举i,一层for枚举j,一层for枚举k的话时间复杂度O(n^3),显然会超时,那么我们预处理数字J的因字数,暴力求即可时间复杂度O(N^2),设定yinzi【i】【j】表示数字i的第j个因子数,同时用cont【i】表示第i个数一共有多少个因子数。
那么我们在求dp【i】【j】的时候的第三层for枚举的时候,直接枚举cont【j】个数即可。时间复杂度优化至O(n^2*cont[i]),明显2000以内的数的因字数不会很多,所以这个时候我们预处理的优化度就显现出来了。
2、那么我们预处理dp【i】【j】之后,其解为:
Σ(dp【k】【i】)【1<=i<=n】
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
#define ll __int64
#define mod 1000000007
int dp[3520][3520];
int yinzi[3520][3520];
int cont[3520];
void initinit()
{
memset(cont,0,sizeof(cont));
for(int i=1;i<=3505;i++)
{
for(int j=1;j<=i;j++)
{
if(i%j==0)
{
yinzi[i][cont[i]++]=j;
}
}
}
}
void init()
{
initinit();
memset(dp,0,sizeof(dp));
for(int i=1;i<=3500;i++)dp[1][i]=1;
for(int i=2;i<=3500;i++)
{
for(int j=1;j<=3500;j++)
{
for(int k=0;k<cont[j];k++)
{
dp[i][j]+=dp[i-1][yinzi[j][k]];
dp[i][j]%=mod;
}
}
}
}
int main()
{
init();
int n,k;
while(~scanf("%d%d",&n,&k))
{
ll sum=0;
for(int i=1;i<=n;i++)
{
sum+=dp[k][i];
sum%=mod;
}
printf("%I64d\n",sum);
}
}