【问题标题】:Formulating dp problem [Codeforces 414 B]制定 dp 问题 [Codeforces 414 B]
【发布时间】:2020-08-11 09:39:27
【问题描述】:

这里都是 problem statement 来自 codeforces 的旧竞赛

l个整数序列b 1, b 2, ..., b l (1 ≤ b 1 ≤ b 2 ≤ ... ≤ b 如果每个数除以(没有余数),则 l ≤ n) 称为好数 序列中的下一个数字。更正式地为所有我 (1 ≤ i ≤ l - 1)。

给定 n 和 k 找到长度为 k 的好序列的数量。作为 答案可以是相当大的打印它模 1000000007 (109 + 7)。

我已将我的dp[i][j] 公式化为长度为i 的好的序列数,以jth 数结尾,转换表为以下伪代码

dp[k][n] = 
  for each factor of n as i do
    for j from 1 to k - 1
      dp[k][n] += dp[j][i]
    end
  end

但在社论中是这样给出的

Lets define dp[i][j] as number of good sequences of length i that ends in j.

Let's denote divisors of j by x1, x2, ..., xl. Then dp[i][j] = sigma dp[i - 1][xr]

但在我的理解中,我们需要两个 sigma,一个用于除数,另一个用于长度。请帮助我纠正我的理解。

我的代码 ->

MOD = 10 ** 9 + 7

N, K = map(int, input().split())

dp = [[0 for _ in range(N + 1)] for _ in range(K + 1)]

for k in range(1, K + 1):
    for n in range(1, N + 1):
        c = 1
        for i in range(1, n):
            if n % i != 0:
                continue
            for j in range(1, k):
                c += dp[j][i]
        dp[k][n] = c

c = 0
for i in range(1, N + 1):
    c = (c + dp[K][i]) % MOD
print(c)

问题链接:https://codeforces.com/problemset/problem/414/B

【问题讨论】:

  • 为什么需要两次求和?如果考虑a_i 的所有可能除数,那么您知道a_i 之前的序列(以所选除数结尾)的长度必须恰好为(i - 1)。 (请注意,问题询问长度确切 k的序列)

标签: algorithm dynamic-programming


【解决方案1】:

所以让我们将 dp[i][j] 定义为长度恰好 i 并且以值 j 作为其最后一个元素的良好序列的数量。

现在,dp[i][j] = Sum(dp[i-1][x]) 对于所有 x s.t. x 是 i 的除数。请注意,x 可以等于 j 本身。

这是真的,因为如果我们已经发现某个长度为 i-1 的序列以某个值 x 结尾,那么我们可以简单地将 j 添加到它的末尾并形成一个满足所有条件的新序列。

我猜你的困惑在于长度。问题是,由于我们当前的长度是 i,我们可以将 j 添加到序列的末尾,前提是它的长度是 i-1,我们不能迭代其他长度。

希望这很清楚。

【讨论】:

  • 谢谢,我错过了 x 可以等于 j 本身。!!
猜你喜欢
  • 1970-01-01
  • 2022-10-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2020-11-26
  • 2021-04-22
相关资源
最近更新 更多