这套题偏难 _(:з」∠)_
A. No Nine
求 [L, R] 的合法数字个数,可以转化为求 [1, x] 的合法数字个数。
不能有数字 9,也就是只允许数字 0~8,这就相当于九进制数,即 [1, x] 的不含 9 的数字个数有 base9(x) 个(x 为不含 9 的十进制数)。而且每连续 9 个不含 9 的数字里,有且只有一个被 9 整除的数(九进制下末位为 0 的数)。因此先把 x 的末位变成 0,让剩余的不含 9 的数字个数能被 9 整除,答案为 brute_force([x - x % 10, x]) + 8 / 9 * base9(x - x % 10)
,两部分分别对应代码里的 ret1
和 ret2
。
1 |
|
B. Sherlock and the Bit Strings
关键信息 Bi - Ai ≤ 15
,递推记录最近的 16 位,f[i][j] 表示前 i 位已确定,并且最后 16 位为 j(j ≤ 2^16)的可行方案数。从后往前(i 从大到小)递推,递推式为 f[i][j] = f[i + 1][shl1[j]] + f[i + 1][shl1[j] ^ 1]
,shl1[j] 和 shl1[j]^1 分别为 j 去掉首位、末尾添加 0 或 1 的状态(保持 16 位)。
对于每个限制 [Ak, Bk, Ck],只需要在求 f[i][j], i = Bk 的时候判断即可,保证不合法的方案最终不会传递到前面。
时间复杂度为 O(2 ^ 16 * (n + k))
,空间复杂度为 O(2 ^ 16 * n)
。
1 |
|
C. King’s Circle
首先必须想好怎样的三个点可以形成矩形:
- 其中两点横坐标或纵坐标相等可以形成矩形;
- 从左向右排列,第二个点最高或最低(形如 ‘⋁’ 或 ‘⋀’),可以形成矩形;
- 横坐标从小到大排列下,只有纵坐标严格递增或严格递减的情况,才不可以形成矩形,且只有这一种不可以形成矩形的情况。
3 的情况比 1 和 2 的情况更好判断,于是把答案转化为 C(n, 3) - 不可以形成矩形的三点集数目
。
考虑每个点 p,从它往四个方向扩展的点集分别记为 n1、n2、n3 和 n4,如下图所示:
{n1 里的任意一点, p, n3 里的任意一点} 和
{n2 里的任意一点, p, n4 里的任意一点} 的三点集不可以形成矩形,这里共有 |n1| * |n3| + |n2| * |n4|
种方案。
这种多维范围查询,可以使用 range tree 这一数据结构,可以参考这个资料:http://www.cs.wustl.edu/~taoju/cse546/lectures/Lecture21_rangequery_2d.pdf。时间复杂度 O(n * log(n) * log(n))
,可以降到 O(n * log(n))
。
以下版本是原生的 range tree,运行 large-practice 数据需要大概 5 分钟。
1 |
|
以下版本利用查询特点进行优化,运行 large-practice 数据需要大概 50 秒。优化的地方包括:
- 由于只有包含端点的查询,第二维 ytree 不使用树结构,使用有序数组;
- 由于查询的 x 有序(升序),手动维护相关的 xtree 节点(xnode 数组)。
1 |
|