SDOI 2017 Round 1 大赏
考虑到写详解有点花时间, 不写又容易忘 = =, 那就写个大概吧.
SD 两轮省选 (可能?) 会比较科学一点吧
不要因为 Round 1 而错怪 SDOI.
「SDOI2017」数字表格
题意简述
求
其中 $f(n)$ 为斐波那契数列数列第 $n$ 项, $1 \le n,m \le 10^6$, 多组测试数据, $1 \le T \le 1000$.
题目链接
看到 $\gcd$ 不如来反演一波. 不妨令 $n \le m$.
枚举约数并整理, 有
由莫比乌斯反演的套路, 得
设 $g(T) = \prod_{d\mid T} f(d) ^ {\mu (\frac{T}{d})}$, 则所求即为
考虑计算 $g(T)$. 可以发现, 由于 $\mu(n)$ 取值只有 $0, -1, 1$, 计算 $g(T)$ 可以通过枚举倍数简单地实现. 时间复杂度 $O(n \ln n)$.
配合前缀积和数论分块即可, 注意快速幂时间复杂度 $O(\log b)$.
时间复杂度 $O(n \log P + n \ln n + T \cdot n \sqrt n \log P)$.
代码实现
1 | // LOJ #2000 |
「SDOI2017」树点涂色
题目链接
解题思路
观察操作 1, 以及初始颜色都不相同, 可以发现每次把一条从根节点开始的链染成新颜色的操作类似与 LCT 中的 access
. 另加考虑可以发现, 某个节点 $u$ 到根节点的颜色数, 就是在 LCT 上经过虚边的个数 + 1. (假设初始状态中, 树上的边在 LCT 上都是虚边)
根据这个思路, 操作 2 可以简单计算, 也就是 dist(u) + dist(v) - 2 * dist(LCA) + 1
. (此处用 dist
指代当前节点到根的颜色数, 因为 LCA 被减两次所以答案 + 1)
那么操作 3 呢? 回想 LCT 维护子树信息的过程, 体现在这道题中也就是在更改 “实儿子” 和 “虚儿子” 子树的信息, 换言之, 子树内加减, 然后维护最值就好了. 可以计算出 DFS 序后使用线段树维护.
实现中在建树的时候直接使用深度作为初始最值, 以及 access
修改的时候需要 findroot
一下找到实际子树的根再修改.
时间复杂度 $O(m \log ^2 n)$, 最近一群毒瘤卡树剖, 不敢再有 log^3 了
代码实现
1 | // LOJ #2001 |
「SDOI2017」序列计数
高一刚学矩阵快速幂的时候整天写斐波那契数列的 n 倍经验 = =
然后某次学长测试, 出了一个矩阵快速幂, 差点就 A 了, 可惜矩阵写反了…
再然后就没独立写出过矩阵快速幂的题了, 凄惨 = =
题目链接
解题思路
要求和是 $p$ 的倍数, 那么显然是模 $p$ 意义下为 $0$ 了. 考虑到至少有一个数为质数的限制可以通过减法原理解决, 即计算一遍所有数的方案数, 再减去只用合数的答案.
容易想到一个暴力 DP:
设 $f(i, j)$ 表示选 $i$ 个数, 加起来模 $p$ 为 $j$ 的方案数. 则
每次选择满足限制的 $k$ 就好了.
观察到 DP 中每次转移都是一样的, 考虑用矩阵快速幂优化.
容易想到 $O(mp)$ 的构造矩阵方法, 考虑在模 $p$ 意义下, 矩阵中某一列 (或者是某一行) 是循环的, 于是可以在 $O(m + p^2)$ 的时间内构造.
具体实现的时候有一些细节, 还是参考代码实现吧.
时间复杂度 $O(m + p^2 + p^3 \log n)$.
代码实现
这道题中, 两个矩阵相乘可以通过某些方法优化到 $O(p^2)$, 研究不懂, $O(p^3)$ 养老…
1 | // LOJ #2002 |
「SDOI2017」新生舞会
题目链接
解题思路
看到式子之后容易联想到 0/1 分数规划. 所以直接考虑二分答案.
假设当前答案 $\ge x$, 也就是
进一步转化,得
然后就可以用二分图最大匹配解决了. 具体地说, 二分图内两两边权 $w_{i, j} = a_{i, j} - b_{i, j} x$, 如果最大权匹配 $\ge 0$ 则当前二分到的 $x$ 合法.
二分图最大权匹配部分采用 KM 算法, 时间复杂度 $O(n^3 \log w)$. 其中 $w$ 为权值上界.
突然有一种工程界很喜欢 KM 算法的错觉.
代码实现
听说写费用流有点卡常? 我这一个写 KM 的哪知道啊 = =
以及二分的时候不要玩弄 eps
, 因为二分边界写挂调了好久.png
1 | // LOJ #2003 |
「SDOI2017」硬币游戏
字符串题啊, 学提高的时候用哈希, 学省选的时候用 SAM 就够了.
不知道从哪里听来这句屁话 = =
题目链接
解题思路
还是 CQzhangyu 讲得好.
代码实现
0.5 ^ 300 = 4.909093465297727e-91
2.0 ^ 300 = 2.037035976334486e+90
你叫我用哪个…
1 | // LOJ #2004 |
「SDOI2017」相关分析
之前听 lxl 讲洛谷网课的时候看他吐槽过 SDOI “那个无聊的东西”, 大概是指的这个吧 (
的确挺无聊的 = =
题目链接
解题思路
读过高中必修课本的 (忘了是哪本了 = =) 都知道, 询问的 $\hat a$ 可以展开, 当然不知道这个式子也是可推的…
对于询问, 直接用线段树维护 $\sum {x_i}, \sum {y_i}, \sum x_i y_i, \sum x_i ^ 2$ 就可以回答了.
区间加… 把这几个东西加起来再展开就好了.
区间赋值… 注意所赋值具有特殊性, 也就是第 $i$ 个位置改成 $i$, 然后再跑一遍区间加的操作就好了.
看错条件多推了一倍的式子, 人没了
代码实现
线段树的细节无非是传标记的时候容易挂… 然后就喜闻乐见地挂了.
1 | // LOJ #2005 |