AtCoder Beginner Contest 248(A~G)
ABC248A Lacked Number
一个看上去比较高端的做法:设 \(w=0\oplus 1\oplus2\oplus\cdots \oplus 9\),其中 \(\oplus\) 表示异或。用 \(w\) 去异或字符串中的每个数即可。
这是因为 \(x\oplus x=0\),出现过的数刚好会被消掉,最后只剩下一个没有出现的数。AC Code
ABC248B Slimes
依照题意模拟即可。AC Code
ABC248C Dice Sum
典中典背包DP。我还写过题解:Link
然后官方题解里面说可以多项式优化,其实也挺板子的。。
ABC248D Range Count Query
不会真的有人写莫队吧
考虑开 \(n\) 个 vector
,第 \(i\) 个 vector
按升序存一下满足 \(a_x=i\) 的所有 \(x\),也就是序列中 \(=i\) 的所有数的下标。
那么查询 \([l,r]\) 内 \(=k\) 的元素个数时,只需要在第 \(k\) 个 vector
内二分出来第一个和最后一个位于 \([l,r]\) 内的数所处的位置,这两个数在这个 vector
中的距离就是答案。复杂度 \(O(n+q\log n)\)。AC Code
ABC248E K-colinear Line
考虑枚举两个点 \(i,j\),然后判断它们是否经过了 \(\ge k\) 个点。
一共有 \(O(n^2)\) 个点对,判断在某条直线上的点数可以直接 \(O(n)\) 做,那么复杂度就是 \(O(n^3)\)。
为了防止算重,需要处理出来每条直线的斜率与截距扔进 map
里面。
我一开始为了避免精度误差直接当做分数存进了 map
里,然后发现巨难写。。
写了半小时交了一发之后还 wa 了。。。心态爆炸.jpg
突然我一拍脑袋,如果有 \(x\) 个点共线,那么我们会枚举这一条直线 \(\dfrac{x(x-1)}{2}\) 次。
那只要每次算的时候加上 \(\dfrac{2}{x(x-1)}\) 不就行了?
开个 double
存答案,最后四舍五入一下就行了。精度完全没有问题的好嘛!!AC Code
ABC248F Keep Connect
场上因为写 G 没时间写这题了。。。场后胡了个 dp,明天起来补orz
ABC248G GCD cost on the tree
这不是我好早之前自己 yy 的点分治题吗.jpg
考虑点分治,对于当前根 \(\text{root}\),设 \(g_u\) 为 \(\text{root}\to u\) 路径上点权 \(\gcd\),\(f_u\) 为 \(u\) 的深度。
依次处理 \(\text{root}\) 的每一棵子树,并维护一个集合 \(S\):
- 对于当前子树内的每个点 \(u\),算出 \(f_u\) 与 \(g_u\),并将 \(\sum_{v\in S}(f_u+f_v)\gcd(g_u,g_v)\) 累计进答案。
- 将每个点 \(u\) 插入进集合内。
现在只需要考虑如何维护集合 \(S\)。
简化一下问题,我们需要维护一个集合 \(S\) ,支持加入一个数,以及对于给定的数 \(y\),查询
注意到
预处理 \(\varphi\),并维护每个数在 \(S\) 中的倍数个数即可。
那么这道题也就相当于带了个权,把贡献拆成两部分就行了。
更具体地,我们要查询的东西相当于
前面一部分就是带了个权,后面一部分就是不带权的情况乘上 \(f_y\)。本质上没有什么变化。
时间复杂度:我们每次加入与删除的复杂度都是 \(O(d(y))\),其中 \(d(x)\) 表示 \(x\) 的约数个数。
随便写个程序验证一下就可以发现 \(\max_{i\in[1,10^5]}d(i)=128\),所以复杂度并不会太高。
总的复杂度为 \(O(nd(V)\log n+V\log V)\),其中 \(V=10^5\) 为值域。\(V\log V\) 来自预处理约数集合。
由于 \(d(V)\) 在大多数情况下只有 \(O(\log V)\),根本卡不满 \(128\),所以常数很小。AC Code