2020年9月12日普及组 T2 序列【DP】

2020年9月12日普及组 T2 序列【DP】_第1张图片
这道题我们的思路是这样的:
首先我们预处理出每个数 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 n1 枚举 (因为滚动数组的无后效性)。

代码

#include
#include
#include
#include
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;
}

你可能感兴趣的:(dp,题解(较高质量))