2386 序列(兼6.4模拟题)

题目

一个长度为k的整数序列b1,b2,…,bk(1≤b1≤b2≤…≤bk≤N)称为“好序列”当且仅当后一个数是前一个数的倍数,即bi+1是bi的倍数对任意的i(1≤i≤k-1)成立。
给定N和k,请算出有多少个长度为k的“好序列”,答案对1000000007取模。
(1<=n,k<=2000)

题解

DP,
f[i,j]表示长度为i的末尾为j的好序列的个数
方程=
f[i,j]=∑f[i,x] (x为j的约数)

由于n和k都比较大,可以想到运用动态规划
设f(i,j)表示序列的前i个数已经确定,并且最后一个数为j的方案数
因为后一个数必须是前一个数的倍数,因此
f(i,j)=Σf(i,x) x为j的约数
可以预先处理处约数
还可考虑,用“正向思维法”对动态规划进行改造:对于当前的状态f(i,j),可以“贡献”哪些状态?f[i+1,j*x] (j*x<=n

时间复杂度O(kn log n)

代码

方法一:

var
  n,k,i,j,ans,t:longint;
  f,a:array[0..2000,0..2000]of longint;
begin
  readln(n,k);
  for i:=1 to n do
    for j:=1 to trunc(sqrt(i)) do
      if i mod j=0 then
        begin
          inc(a[i,0]);
          a[i,a[i,0]]:=j;
          if i div j<>j then
            begin
              inc(a[i,0]);
              a[i,a[i,0]]:=i div j;
            end;
        end;
  for i:=1 to n do
    f[0,i]:=1;
  for i:=1 to k do
    for j:=1 to n do
      for t:=1 to a[j,0] do
        f[i,j]:=(f[i,j]+f[i-1,a[j,t]]) mod 1000000007;
  for i:=1 to n do
    f[k,0]:=(f[k,0]+f[k-1,i]) mod 1000000007;
  writeln(f[k,0]);
end.

方法二:

var
  i,j,k,l,n,ans:longint;
  f:array[1..2000,1..2000]of longint;
begin
  readln(n,k);
  for i:=1 to n do
    f[1,i]:=1;
  for i:=1 to k do
    for j:=1 to n do
      for l:=1 to n div j do
        f[i+1,j*l]:=(f[i+1,j*l]+f[i,j]) mod 1000000007;
  for i:=1 to n do
    ans:=(ans+f[k,i]) mod 1000000007;
  writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值