题解
比赛之后有大佬说这题可以用圆的反演来做,学习了一下。
以两个大圆的切点为反演中心,任取一个反演半径,两个大圆会变成两条平行线。再考虑小圆的反演,由于相切的性质不变,小圆的反演圆就是一列夹在平行线中间的小圆。
示意图:
当然这样还是 $O(n)$ 的,但是看题目里的图就知道小圆会越来越小,小到一定程度以后直接不考虑就行了。
代码
1 | #include <bits/stdc++.h> |
尾巴
大佬不愿意透露id,鸣谢csust?
比赛之后有大佬说这题可以用圆的反演来做,学习了一下。
以两个大圆的切点为反演中心,任取一个反演半径,两个大圆会变成两条平行线。再考虑小圆的反演,由于相切的性质不变,小圆的反演圆就是一列夹在平行线中间的小圆。
示意图:
当然这样还是 $O(n)$ 的,但是看题目里的图就知道小圆会越来越小,小到一定程度以后直接不考虑就行了。
1 | #include <bits/stdc++.h> |
大佬不愿意透露id,鸣谢csust?
定义函数 $f(n,k)$,当 $n$ 在 $k$ 进制表示为回文数时,$f(n,k)=k$;否则 $f(n,k)=1$ 。求 $\sum_{i=L}^{R}\sum_{j=l}^{r}f(i,j)$ 。($1 \leq T \leq 10^5, 1 \leq L \leq R \leq 10^9, 2 \leq l \leq r \leq 36$)
可以发现 $l,r$ 的范围很小,直接枚举 $j$ 代表 $j$ 进制,对于 $i$ 用数位dp统计即可。
比赛的时候竟然没做这一题。。。蠢死了 ┭┮﹏┭┮
1 | #include <bits/stdc++.h> |
仅含题解,代码详见github。喜欢的话点个star
感觉题意有点绕。。。其实就是每个节点一开始就有整个子树的序列,那么这个序列一定是先输入小的再输入大的才能最优。
不过这个事情也不是两个有序表合并这么简单,因为对于两个序列,只有把某个序列的数一个一个地插入到另一个才能算出答案。这时候就要用到启发式合并,什么是启发式的策略,通俗来讲就是人脑比较倾向于选择的策略。比如在这里就是把短的序列一个一个插到长的里面,比赛的写的线段树合并结果写了一大坨还没调出来,太蠢了😂。。。然后照着题解写了一个树状数组。。。
代码见附录,dfs用来得到轻重儿子,solve就是插入和合并,要递归重儿子时直接把轻儿子的全部删掉就行了。
求 $f(n)=\sum_{i=1}^{n}\sum_{j=1}^{i} \left\lceil \frac{i}{j} \right\rceil \left[ (i, j) = 1\right]$ 。
比赛的时候算是瞎猜了一下。。。其实这题反演的理论性还是很好的。
以下 $n,i,j,k,d$ 均为正整数,且用 $(i,j)$ 表示 $i$ 和 $j$ 的最大公约数。
#1553 : 区间统计 中文题。
首先预处理所有幂次的结果,$O(NK)$;还有IO时间一定要注意。以下均不讨论。
一看题,无修改区间询问,莫队走起。但是用map复杂度太高了,没算错的话应该是 $O(n^{1.5}logn+m\sqrt{n})$ 。
考虑到A[]的范围不大,可以对A[]计数,不过没什么卵用。但是对A[]计数以后可以发现,我们不仅可以对值计数还可以对次数计数,也就是说has[i]表示有多少数在当前询问中的出现次数等于 i 。
到这里还是比较容易的,但是如果直接扫has[]复杂度并没有降低 $O(n^{1.5}+mn)$ 。。。
仍然是考虑分治思想,一次询问最多是整个区间,整个区间中出现次数大于 $\sqrt{n}$ 的数不会超过 $\sqrt{n}$ 个,还可以进行另外的预处理,我就直接multiset暴力了。。。复杂度大概是 $O(n^{1.5}+m\sqrt{n}+(n+m)log{\sqrt{n}})$ 。。。(已经不会算了 _(:△」∠)_ )
1 | #include <bits/stdc++.h> |
有一个长度为 $n$ 的整数序列 ${a_n}$,对其做 $m$ 次前缀异或和,求最终的序列。
对这个过程手动模拟几行,注意不要消去,可以发现第 $m$ 次第 $i$ 个数的结果包含了 $C_{m-1+i-j}^{i-j}$ 次第 $j$ 个数($j\le i$) 。
首先我们需要判断它的奇偶性。奇偶性相当于2进制的结果,2为质数,可以使用Lucas定理。2进制的每一位只有四种情况,其中 $C_{0}^{1}=0,C_{0}^{0}=C_{1}^{0}=C_{1}^{1}=1$ 。
将 $m-1$ 和 $i-j$ 的每一位展开,在第 $k$ 位上,如果 $m-1$ 和 $i-j$ 都是 1,那么结果就是 0 。
从小到大枚举 $k$ ,表示 $i-j$ 的第 $k$ 位为 1,若 $m-1$ 的第 $k$ 位不为 1,那么直接更新a序列本身。也就是说,每次只用满足 $i-j=2^{k}$ 的 $a[j]$ 更新 $a[i]$,然而此时的 $a[j]$ 已经被 $k$ 取 $0\dots k-1$ 更新过了,所以相当于考虑了 $i-j$ 在 $0\dots k$ 位的所有情况。
1 | #include <bits/stdc++.h> |
给出一棵树,要求支持:
首先考虑在序列上的问题,可以用线段树维护颜色段数以及左右端的颜色。
对于树上的问题,用树链剖分变成序列上的问题即可。
但是写起来并不是那么好写的。。。泄露出来的标程写了 6KB 还特别恶心。。。
还好我搜到了一份非常漂亮的代码,同时建议做树链剖分时把线段树整体作为一个结构体~
回答询问时还要注意因为两条链都是由浅到深的,拼起来必须有一个要反过来。
1 | #include <bits/stdc++.h> |
输出[1…n]的质数个数 (1 <= n <= 1e11) 。时间限制6s,空间限制64M 。
很显然,要用线性筛的话时间和空间都不够。
有一种Meissel–Lehmer算法可以解决该问题,不过本文要介绍的是一种dp解法。
定义$SR(n,p)$为,$2…n$被小于等于$p$的质数筛后剩下的数的个数;也就是说,在n的范围内,是质数,或者是只由大于$p$的质数相乘得到的数的个数。
记小于等于$n$的质数个数为$\pi(n)$,那么显然有$SR(n,n)=\pi(n)$ 。
对$SR(n,p)$分两类讨论:
当然因为空间限制肯定不能直接这样dp,考虑到整个过程中只用到了 $p$ 和 $\frac{n}{p}$,我们直接分为两段dp, 用H[k]表示 $k\le \sqrt{n}$ 时 $SR(\frac{n}{k},p)$ 的值,用L[k]表示 $k \le \sqrt{n}$ 时 $SR(k,p)$ 的值。
先放出代码,原作者*adkroxx*:
仅含题解,代码详见github。喜欢的话点个star
易得,$g_m(x)=f(x-\sum a_i)$ 。
记 $S=\sum a_i $,代入:
$$\large \begin{equation}\begin{split}
g_m(x)&=\sum_{i=0}^{n}c_i(x-S)^i \\
&=\sum_{i=0}^{n}c_i\sum_{j=0}^{i}C_{i}^{j}x^j(-S)^{i-j} \\
&=x^0\sum_{j=0}^{n}c_jC_{j}^{0}(-S)^{j-0}+\cdots+x^n\sum_{j=0}^{n}c_jC_{j}^{n}(-S)^{j-n} \\
&=\sum_{i=0}^{n}x^i\sum_{j=0}^{n}c_jC_{j}^{i}(-S)^{j-i} \\
&=\sum_{i=0}^{n}x^i\sum_{j=i}^{n}c_j\cfrac{j!}{i!\cdot (j-i)!}(-S)^{j-i}
\end{split}\end{equation}$$
$\large \therefore b_i=\cfrac{1}{i!}\sum_{j=i}^{n}j!c_j\cdot \cfrac{(-S)^{j-i}}{(j-i)!}$
记$\large A_i=i!c_i,B_i=i!b_i,d_i=A_{n-i},e_i=\cfrac{(-S)^{i}}{i!},(1\le i\le n)$
$\large B_i=\sum_{k=i}^{n}A_k\cdot e_{k-i}=\sum_{k=0}^{n-i}d_{n-i-k}e_{k}$
考虑多项式乘法:
$A(x) = \sum_{i=0}^{n}a_ix^{i}$
$B(x) = \sum_{i=0}^{n}b_ix^{i}$
$C(x) = A(x)B(x) = \sum_{i=0}^{2n}c_ix^{i}$
$c_j = \sum_{i=0}^{j}a_ib_{j-i}$,
所以$B_i$即为多项式$D(x)E(x)$第$n-i$项的系数。
仅含题解,代码详见github。喜欢的话点个star
每个字符对答案的贡献都可以看作一个26进制的数字,直接按26进制的从高到低位比较大小。由排序不等式,显然贡献越大的对应的数字越大时答案最大。
注意点:一个字符一旦做过最高位(位数大于1)就不能被赋值为0。
单独考虑每一种颜色,答案就是对于每种颜色,至少经过一次这种颜色的路径条数之和。反过来思考只需要求有多少条路径没有经过这种颜色即可。
记$u$的颜色为col[u]。对于$v$,若在子树$v$中取$x$,在子树$v$外取$y$,则这些路径一定会经过col[v]。那么有两个推论: