题意:
给出两个数,n、k。
要求一个序列中后一位数对前一位数求余为0。
n是序列内最大能赋的值,k是所求序列的长度。
然后呢,求最多有多少种序列。
and不要忘记对答案求余——mod=1e9+7
题解:
看的这位dalao的题解,讲的好详细:点我点我。包括如何往dp这方面想,对于我这个dp菜狗很有帮助hhh。
写出dp的状态转移方程:dp[i][j]=求和(dp[k][j-1])///k是i的因数
然后就是具体的处理了,看代码注释啦。
代码:
#include <bits/stdc++.h>
using namespace std;
#define sc scanf
#define pr printf
const int maxn=2e3+3;
const int mod=1e9+7;
#define ll long long
ll dp[maxn][maxn];//dp[某数][数列长度]
//式子:dp[i][j]=求和(dp[k][j-1])///k是i的因数
vector<int>ve[maxn];
int main()
{
int n,k;
cin>>n>>k;
//预处理i的因数
for(int i=2; i<=n; i++)
{
for(int j=1; j<=sqrt(i); j++)
{
if(i%j==0)
{
ve[i].push_back(j);
if(j!=i/j)ve[i].push_back(i/j);
}
}
}
//初始化
for(int i=1; i<=n; i++)dp[i][1]=1;
for(int i=1; i<=k; i++)dp[1][i]=1;
//
for(int i=1; i<=n; i++)
for(int j=1; j<=k; j++)
{
//dp[i][j]
for(int k=0; k<ve[i].size(); k++)
dp[i][j]=(dp[i][j]+dp[ve[i][k]][j-1])%mod;
}
//
ll sum=0;
for(int i=1;i<=n;i++)sum=(sum+dp[i][k])%mod;
cout<<sum<<endl;
return 0;
}