考虑 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. Cortex-M3 入门指南(三):时钟总线与复位时钟控制器

    [reset clock control  复位和时钟控制器] 时钟信号对于处理器非常重要,比如我们熟悉的 CPU 就是由时钟信号驱动的,而主频就是内核的的时钟信号频率.Cortex-M3 有着复杂的 ...

  2. webuploader的一些体验

    WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件.支持大文件分片并发上传. 具体api文档参考:http://fex.b ...

  3. phpcms9 从注入点入手和 从前台getshell

    弄了3天了  这个点 总结一下这三天的坑吧 0X01 注入点入手 /index.php?m=wap&c=index&a=init&siteid=1 获取cookie 传给 us ...

  4. 【Nginx】 linux环境下安装nginx步骤

    开始前,请确认gcc g++开发类库是否装好,默认已经安装. centos平台编译环境使用如下指令 安装make: yum -y install gcc automake autoconf libto ...

  5. Mybatis 实体类使用@Accessors(chain = true)注解时,对应的mapper xml 报错

    去掉这个注解就行了 应该是 mybatis 会调用实体类的 getter  setter 方法, 返回值可能会有所影响

  6. ajax 415

    ajax 发送post请求是出现415错误,是ajax的格式有问题,如下. $.ajax({ type: 'POST', url: '/login', data: { "username&q ...

  7. JS基础_原型对象

    原型prototype 我们创建的每一个函数,解析器都会向函数中添加一个属性prototype 这个属性,对应着一个对象,这个对象就是我们所谓的原型对象 1.如果函数作为普通函数调用prototype ...

  8. Linux上Python的安装升级

    1.下载 cd /usr/local/src/ wget https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz 2.安装,在/usr/loc ...

  9. 学习 vue 需要了解的内容

    总结 vue 的目录 1. vue 基础 指令 事件 动态的属性 组件 动画 2. vue 组件通信 1. 父传子 props 2. 子传父 ref 3. 插槽 4. 组件的生命周期 3. vue 的 ...

  10. 开源运维自动化平台-opendevops

    开源运维自动化平台-opendevops 简介 官网 | Github|  在线体验 CODO是一款为用户提供企业多混合云.自动化运维.完全开源的云管理平台. CODO前端基于Vue iview开发. ...