序列
时间限制:1000MS
内存限制:128000KB
题目描述
一个长度为k的整数序列b1,b2,…,bk(1≤b1≤b2≤…≤bk≤N)称为“好序列”当且仅当后一个数是前一个数的倍数,即bi+1是bi的倍数对任意的i(1≤i≤k-1)成立。
给定N和k,请算出有多少个长度为k的“好序列”,答案对1000000007取模。
输入
输入共1行,包含2个用空格隔开的整数N和k。
输出
输出共1行,包含一个整数,表示长度为k的“好序列”的个数对1000000007取模后的结果。
输入样例
3 2
输出样例
5
说明
【输入输出样例说明】
“好序列”为:[1,1],[1,2],[1,3],[2,2],[3,3]。
【数据说明】
对于40%的数据,1≤N≤30,1≤k≤10。
对于100%的数据,1≤N≤2000,1≤k≤2000。
解题思路
DP
F[i][j]表示序列长度为i且序列最后一个数b[i] =j的“好序列”的个数
F[i][j]=∑F[i-1][x]其中x为j的约数
可以先预处理出1-n每个数的约数
∑:为求和
AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
long long n,k,s,k1,b[2005],a[2005][2005],f[2005][2005];
int main()
{
scanf("%lld%lld",&n,&k1);
for(long long i=1;i<=n;i++)//预处理约数
for(long long j=1;j<=sqrt(i);j++)
if(i%j==0)
{
if(j*j==i)a[i][++b[i]]=j;//特判
else a[i][++b[i]]=j,a[i][++b[i]]=i/j;
}
for(long long i=1;i<=n;i++)//初值
f[1][i]=1;
for(long long i=2;i<=k1;i++)//dp
for(long long j=1;j<=n;j++)
for(long long k=1;k<=b[j];k++)
f[i][j]=(f[i][j]+f[i-1][a[j][k]])%1000000007;//取模
for(long long i=1;i<=n;i++)//最后每个都要累加
s=(s+f[k1][i])%1000000007;
printf("%lld",s);
return 0;
}
下面附本次比赛的其它题目
2020.9.12 SSL普及组模拟(第1题)(字符串)
2020.9.12 SSL普及组模拟(第2题)(序列)(dp)
2020.9.12 SSL普及组模拟(第3题)(游戏)(bfs20分)(求找问题)
2020.9.12 SSL普及组模拟(第4题)(树)(暴力邻接表80)
2020.9.12 SSL普及组模拟(总结)