ABC133F Small Products
考虑 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}] $
容易证明下列几个不等式
- $\floor{N/i} \ge \floor{N/(i + 1)}$
- $\floor{N/\floor{N/i}} \ge i$
- $\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的更多相关文章
- Building third-party products of OpenCascade
Building third-party products of OpenCascade eryar@163.com Available distributives of third-party pr ...
- 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 ...
- 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 ...
- magento添加多个产品到购物车(Add multiple products to cart )
Step 1app\design\frontend\base\default\template\catalog\product\list.phtml<?php $_productColl ...
- 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 ...
- 读书笔记-《Training Products of Experts by Minimizing Contrastive Divergence》
Training Products of Experts by Minimizing Contrastive Divergence(以下简称 PoE)是 DBN 和深度学习理论的 肇始之篇,最近在爬梳 ...
- /users/products.:format 这种写法的其对应解析字符写法
“products.:format" 这种写法可以有对应的下面两种路由形式 /products.json /products.xml "products.:format?" ...
- 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 ...
- Popular Products
Popular Products 描述 Given N lists of customer purchase, your task is to find the products that appea ...
随机推荐
- 关于在mac上使用valet集成环境添加memcache扩展
由于业务要求需要使用到memcache,直接使用brew安装在phpinfo上面显示并没有加载成功,使用以下方法时我们需要先卸载之前已经安装完成的memcache brew unlink php70- ...
- Codeforces 785 E. Anton and Permutation(分块,树状数组)
Codeforces 785 E. Anton and Permutation 题目大意:给出n,q.n代表有一个元素从1到n的数组(对应索引1~n),q表示有q个查询.每次查询给出两个数l,r,要求 ...
- Laydate 使用注意事项
1.laydate 切记不能放在laytpl 模板语法中使用,否则可能会导致无法触发的情况 不在laytpl中使用 <div class="layui-form-item"& ...
- [CSP-S模拟测试]:联合权值·改(暴力)
题目传送门(内部题143) 输入格式 输入文件的第一行为三个整数$n,m,t$.其中$t$是数据类型. 接下来$m$行,每行两个正整数$u,v$,表示图中的一条边.数据保证不存在重边或自环的情况. ...
- 从零开始学习Gradle之三---多项目构建
随着信息化的快速发展,IT项目变得越来越复杂,通常都是由多个子系统共同协作完成.对于这种多系统.多项目的情况,很多构建工具都已经提供了不错的支持,像maven.ant.Gradle除了借鉴了an ...
- 关于OpenModelica的编译
由于工作需要,最近对OpenModelica进行二次开发,由于国内资料也比较少,所以踩了一些坑,近期计划把OpenModelica的编译,msys,及OpenModelica里面比较关键的部分OMEd ...
- EBS 修改系统颜色
1)修改 配置文件: Java 色彩设计,选择相应的颜色 2)清理高速缓存 注:如果不清理缓存,则要等15分钟后才显示变成新设定的颜色
- 用Java实现一个二叉树
介绍 使用Java实现一个int值类型的排序二叉树 二叉树 二叉树是一个递归的数据结构,每个节点最多有两个子节点. 通常二叉树是二分查找树,每个节点它的值大于或者等于在它左子树节点上的值,小于或者等于 ...
- 6.HBase时髦谨慎财会会计
1.基本概念和原理 2.核心知识点 3.安装部署 4.Hbase开发
- [go]go环境安装-解决安装包不能访问golang.org问题
安装go和vscode vscode插件列表选择go,安装即可,其他插件暂不安装 手动安装一些vscode配套的调试工具等 直接vscode-go,然后点下面的go-tools就能找到 go get ...