这道题我们的思路是这样的:
首先我们预处理出每个数 x x x 的因数,
这样方便后边DP,也能省时。
注意要特判 i = = j i==j i==j 的情况,因为这是滚动数组,不然会算重。
然后设 f [ i ] f[i] f[i] 表示以 i i i 为尾的好序列的个数
可得动态转移方程为:
f [ j ] = ( f [ j ] + f [ y s [ j ] [ k 1 ] ] ) m o d 1000000007 ; f[j]=(f[j]+f[ys[j][k1]])\mod1000000007; f[j]=(f[j]+f[ys[j][k1]])mod1000000007;
注意 j j j 从 n − 1 n-1 n−1 枚举 (因为滚动数组的无后效性)。
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int ys[2010][2010],c[4000000];
int n,k,ans,f[100010];
int main()
{
cin>>n>>k;
for(int i=1; i<=n; i++)
for(int j=1; j<i; j++) //j不能等于i,因为f是滚动数组(j=i就会加重)
{
if(i%j==0) //j是i的因数;
ys[i][++c[i]]=j;
}
for(int i=1; i<=n; i++) //赋第一行初值
f[i]=1;
for(int i=2; i<=k; i++)
for(int j=n; j>1; j--) //保证无后效性
for(int k1=1; k1<=c[j]; k1++)
f[j]=(f[j]+f[ys[j][k1]])%1000000007;//当前行+上一行
for(int i=1; i<=n; i++)
ans=(ans+f[i])%1000000007; //累加每一位以当前i为结尾的所有状态。
cout<<ans%1000000007;
return 0;
}