考虑 DP。

状态

令 $f[\ell][x]$ 表示长度为 $\ell$,首项不超过 $x$ 的序列的个数。

答案是 $f[K][N]$。

有递推 $f[\ell][x] = f[\ell][x - 1] + f[\ell - 1][\floor{N/x}]$。照这个递推式求解,复杂度度太高;把它改成

$f[\ell][x] = \sum_{y = 1}^{x} f[\ell - 1][\floor{N/y}]$ 也就是枚举首项。

我们的目标是求出 $f[K][N]$,结合递推式来看,可以发现我们需要计算的状态的第二维都可以写成 $\floor{N/i}$。而我们熟知 $\floor{N/i}$ 的不同取值不超过 $2 \sqrt{N}$ 个。因此需要计算的状态不超过 $2K\sqrt{N}$ 个。

先来解决状态表示的问题,也就是 $\floor{N/i}$ 的表示问题。虽然 $\floor{N/i}$ 的取值不超过 $2\sqrt{N}$ 个,但是不能直接以 $\floor{N/i}$ 作为数组下标。可以这样做,对于 $\color{blue}{ i \le \sqrt{N} }$,用 $i$ 表示 $\floor{N/i}$,对于 $\color{red}{ i \ge \sqrt{N} }$,直接以 $\floor{N/i}$ 作为下标。从代码实现的角度说就是开两个数组,$f_1[1..K][1..\floor{\sqrt N}],\ f_2[1..K][1..\floor{\sqrt N}]$,$f_1[\ell][i] := f[\ell][i]$,$f_2[\ell][i] := f[\ell][\floor{N/i}]$。

注①:当 $N$ 是完全平方数时,$i \le \sqrt N$ 与 $i \ge \sqrt N$ 这两段中都含有 $\sqrt{N}$,这并不会造成问题。实际上分段时两侧都取等号是有意为之,这样可以使得递推式更简洁并且没有 corner case。这种分段方法适用于许多跟 $\floor{N/i}$ 相关的分块问题。

注②:关于上一段所说的“对于 $i \le \sqrt N$,用 $i$ 表示 $\floor{N/i}$”,我们不需要关心 $i \mapsto \floor{N/i}$ 是不是单射。这里所谓“表示 $\floor{N/i}$”是说设计一种方法来把所有需要计算的 $f[\ell][\floor{N/i}]$ 紧凑地存到数组里并且可以快速地由 $\ell, i$ 这两个 key 查到 $f[\ell][\floor{N/i}]$ 的值。不过可以证明,对于 $i \le \sqrt{N}$,$i \mapsto \floor{N/i}$ 确实是单射。

递推

对于 $f_1$,有递推

$f_1[l][x] = f_1[l][x - 1] + f[l - 1][\floor{N/x}]$

由于 $1 \le x \le \floor{\sqrt{N}}$,有 $f[l - 1][\floor{N/x}] = f_2[l-1][x]$,从而有

$f_1[l][x] = f_1[l][x - 1] + f_2[l-1][x]$

对于 $f_2$,有递推式

$f_2[l][i] = f_2[l][i+1] + \sum_{x=\floor{N/(i+1)} + 1}^{\floor{N/i}} f[l -1][\floor{N/x}] $

容易证明下列几个不等式

  1. $\floor{N/i} \ge \floor{N/(i + 1)}$
  2. $\floor{N/\floor{N/i}} \ge i$
  3. $\floor{N / \left(\floor{N/i} + 1 \right) } < i$

只证第 3 个。

设 $ \floor{\frac{N}{i}} = t$,我们有

$ t \le \frac{N}{i} < t + 1 \iff it \le N < i(t + 1) \iff i\frac{t}{t + 1} \le \frac{N}{t + 1} < i \implies \floor{\frac{N}{t + 1}} < i$

因此我们有 $i \le \floor{\frac{N}{x}} < i + 1$,即对于 $\floor{\frac{N}{i + 1}} < x \le \floor{\frac Ni}$ 恒有 $ \floor{\frac{N}{x}} = i $,这里我们得到一个很有用的等式

若 $\floor{\frac{N}{i}} \ge \floor{\frac{N}{i+1}}$,则

$f[l][\floor{\frac{N}{i}}] = f[l][\floor{N/(i + 1)}] + \left( \floor{\frac{N}{i}} - \floor{\frac{N}{i+1}} \right) f[l - 1][i] $

并且当 $\floor{\frac{N}{i}} > \floor{\frac{N}{i+1}}$ 时,$i$ 可表为 $\floor{ \frac{N}{ \floor{ \frac{N}{i} } } }$

从而有

\begin{aligned}

f_2[l][i] &= f_2[l][i+1] + \left( \floor{\frac{N}{i}} - \floor{\frac{N}{i+1}} \right) f[l - 1][i] \\

&= f_2[l][i+1] + \left( \floor{\frac{N}{i}} - \floor{\frac{N}{i+1}} \right) f_1[l - 1][i]

\end{aligned}

$f_2$ 的边界条件有两个:

1.

$f_2[1][i] = \floor{ \frac{N}{i} } $

2.

\begin{aligned} f_2[l][\floor{\sqrt{N}}] &:= f[l][\floor{\frac{N}{\floor{\sqrt N}}}] \\

&= f[l][\floor{\frac{N}{\floor{\sqrt N}+1}}] + \left( \floor{ \frac{N}{ \floor{\sqrt{N}} } } - \floor{ \frac{N}{\floor{\sqrt N}+1} } \right) f[l - 1][\floor{ \sqrt{N} } ] \\

&= f_1[l][\floor{\frac{N}{\floor{\sqrt N}+1}}] + \left(\floor{\frac{N}{\floor{\sqrt{N}}}} - \floor{\frac{N}{\floor{\sqrt{N}} + 1}} \right) f_1[l - 1][\floor{ \sqrt{N} } ]

\end{aligned}

代码

int main() {

    int n, k;
scan(n, k);
int r = sqrt(n + 0.5); // r is defined to be floor(sqrt{n})
vv<int> f1(k + 1, vi(r + 1)); // f1[len][i]:长为len,首项 <= i
vv<int> f2(k + 1, vi(r + 1)); // f2[len][i]:长为len,首项 <= n/i up (i, 1, r) {
f1[1][i]=i;
}
up (i, 1, r) {
f2[1][i] = n / i;
}
up (l, 2, k) {
up (i, 1, r) {
f1[l][i] = f1[l][i - 1] + f2[l - 1][i];
if (f1[l][i] >= mod) {
f1[l][i] -= mod;
}
}
f2[l][r] = f1[l][n/(r + 1)] + (ll)(n / r - (n / (r + 1))) * f1[l - 1][r] % mod;
if (f2[l][r] >= mod) {
f2[l][r] -= mod;
}
down (i, r - 1, 1) {
f2[l][i] = f2[l][i + 1] + (ll)(n / i - (n / (i + 1))) * f1[l - 1][i] % mod;
if (f2[l][i] >= mod) {
f2[l][i] -= mod;
}
}
}
println(f2[k][1]); return 0;
}

从另一个角度看待这个问题。以下所有 / 运算都向下取整。

取一个数字 m,求出 f[L][1..m]

f[L][i] = f[L][i-1] + f[L-1][N/i]

开一个数组 g[1..m],g[L][i] := f[L][N/i]

问题归结为如何计算 g[L][i]

上面已经得到

g[L][i] = g[L][i+1] + (L/i - L/(i+1))*f[L-1][i]

整个计算过程如下

for i = 1 to m

f[1][i] = i

g[1][i] = N/i

for L = 1 to K

f[L][0] = 0

for L = 2 to K

for i = 1 to m

f[L][i] = f[L][i-1] + g[L-1][i]

// compute g[L][m]

for i = m - 1 down to 1

g[L][i] = g[L][i+1] + (L/i - L/(i+1)) * f[L-1][i]

问题进一步归结为如何计算 g[L][m],即 f[L][N/m]

若 N/m <= m 则 f[L][N/m] 已经算出来了,不成问题。

若 N/m > m 但 N/(m + 1) <= m 则 f[L][N/m] = f[L][N/(m+1)] + (N/m - (N/(m+1))*f[L-1][m],也不成问题。

所以保险的办法是取 m 使得 N/(m + 1) <= m,取 m = floor(sqrt(N)) 就可以保证 N/(m+1) <= m。证明:m+1 > sqrt(N) 因此 N/(m+1) < sqrt(n) <= m 。

取 m = floor(sqrt(N)) + 1 可以保证 N / m < m。证明 m > sqrt(N),所以 N / m < sqrt(N) <= floor(sqrt(N)) < m。

ABC133F Small Products的更多相关文章

  1. Building third-party products of OpenCascade

    Building third-party products of OpenCascade eryar@163.com Available distributives of third-party pr ...

  2. SharePoint Configuration Wizard - Unable to upgrade SharePoint Products and Technologies because an upgrade is already in progress

    故障描述 当要运行SharePonit Products and Technologies Configuration Wizard的时候,出现了如下图所示的错误提示. 错误信息为: Unable t ...

  3. Registry values for ProductID and LocaleID for AutoCAD and the vertical products

    原文地址:http://adndevblog.typepad.com/autocad/2013/08/registry-values-for-productid-and-localeid-for-au ...

  4. magento添加多个产品到购物车(Add multiple products to cart )

    Step  1app\design\frontend\base\default\template\catalog\product\list.phtml<?php    $_productColl ...

  5. FVDI Commander products be replaced SVDI tools,really?

    You may have heard that some FVDI Commander products are being replaced by the new SVDI tools. This ...

  6. 读书笔记-《Training Products of Experts by Minimizing Contrastive Divergence》

    Training Products of Experts by Minimizing Contrastive Divergence(以下简称 PoE)是 DBN 和深度学习理论的 肇始之篇,最近在爬梳 ...

  7. /users/products.:format 这种写法的其对应解析字符写法

    “products.:format" 这种写法可以有对应的下面两种路由形式 /products.json /products.xml "products.:format?" ...

  8. Amazon.com: NEW VI AND VIM EDITOR KEYBOARD STICKER: Office Products

    Amazon.com: NEW VI AND VIM EDITOR KEYBOARD STICKER: Office Products NEW VI AND VIM EDITOR KEYBOARD S ...

  9. Popular Products

    Popular Products 描述 Given N lists of customer purchase, your task is to find the products that appea ...

随机推荐

  1. zabbix企业微信告警配置教程

    前言: zabbix企业微信告警只需要配置一次就可以使用很久了,但是发现再次配置时,总会有遗忘,很麻烦又要去重新熟悉,所以,现在记录一份详细的配置过程,方便日后再次配置. 1.zabbix_serve ...

  2. 使用matplotlib绘制常用图表(3)-其他图表绘制

    一.绘制三点图 """ 三月份最高气温 a = [12,15,18,6,7,5,6,8,9,10,15,10,4,5,11,10,5,6,12,15,10,5,14,10 ...

  3. 25.Python逻辑运算符及其用法

    逻辑运算符是对真和假两种布尔值进行运算(操作 bool 类型的变量.常量或表达式),逻辑运算的返回值也是 bool 类型值. Python 中的逻辑运算符主要包括 and(逻辑与).or(逻辑或)以及 ...

  4. 学号 20175329 《Java程序设计》第10周学习总结

    20175329 <Java程序设计>第十周学习总结 教材学习内容总结 线程与进程 进程时程序的一次动态执行过程.线程是比进程更小的执行单位,一个进程在其执行过程中,可以产生多个线程. J ...

  5. TCP主动打开 之 第三次握手-发送ACK

    假定客户端执行主动打开,并且已经收到服务器发送的第二次握手包SYN+ACK,在经过一系列处理之后,客户端发送第三次握手包ACK到服务器:其流程比较简单,主要是分配skb,初始化ack包并发送:需要注意 ...

  6. Fastadmin 后台编辑,或者添加的时候,出现的问题

    1.情况如图:编辑的时候,这个关联id,默认查出来的是用户昵称,如果要显示用户名,该怎么修改,不要着急,听我慢慢道来 2.首先要找到 编辑页面,检查问题 3.完成

  7. leetcode-hard-array-287. Find the Duplicate Number

    mycode   77.79% class Solution(object): def findDuplicate(self, nums): """ :type nums ...

  8. ubuntu 18.04 64bit下如何安装安卓虚拟机anbox?

    一. 安装snapd sudo apt-get install snapd 二. 安装adb sudo apt-get install adb 三. 安装必要的内核模块 wget https://la ...

  9. Jdbc中大文本类型的处理

    Oracle中大文本数据类型, Clob    长文本类型   (MySQL中不支持,使用的是text) Blob    二进制类型 MySQL数据库, Text    长文本类型 Blob    二 ...

  10. 使用 QQ 邮箱发送邮件报错:java.net.SocketTimeoutException: Read timed out. Failed messages: javax.mail.MessagingException: Exception reading response

    使用 QQ 邮箱发送邮件报错:java.net.SocketTimeoutException: Read timed out. Failed messages: javax.mail.Messagin ...