写在前面:为了保护正睿题目版权,这里不放题面,只写题解。
- A
\(21pts:\)
随便枚举,随便爆搜就好了。
\(65pts:\)
比较显然的dp,设\(f_{i,j,k}\)表示在子树\(i\)中,两个赞助商分别选了\(j,k\)个的最优解。
对枚举的上下界卡的紧一点,按照树上背包的聚合分析,复杂度是\(O(n^3)\)的,可以通过。
\(100pts:\)
观察数据范围可以发现,这题的子树大小限制可以抽象成一个经典的网络流模型。
跑一个最大费用流就好了。
我写丑了,每个点拆了\(5\)个点出来,然而还是跑的飞快。
- B
\(22pts:\)
枚举全排列/状压。
\(100pts:\)
这题非正解不太好写,直接上正解吧。
先考虑什么时候无解。随便弄一棵生成树出来,如果\(\sum a_i<\sum w_i\),显然无解。
现在我们要证明,只要\(\sum a_i \geq \sum w_i\),一定有解。
考虑我们缩点缩到一个局面,此时所有边都无法缩起来。此时对于每条边\((u_i,v_i,w_i)\),都有\(w_i>a_{u_i}+a_{v_i}\)。
将所有不等式加起来,我们得到\(\sum w_i > \sum a_i\cdot dgr_i\geq \sum a_i\),显然与我们之前的假设矛盾。
所以,我们证明了对于一棵生成树,只要\(\sum a_i \geq \sum w_i\),一定有解。那么显然取最小生成树最优。
那么我们考虑对一个满足\(\sum a_i \geq \sum w_i\)的树,如何构造出一种方案。
首先设\(s_i=a_i + \sum_{j\in subtree_i} a_j-w_{(j,fa_j)}\),即\(i\)点子树中所有点权和与边权和之差。
对每个点\(i\),我们算出它的每个儿子\(j\)的\(s_j-w_{(j,i)}\),设这个值为\(v_j\),按照\(v_j\)把它的儿子从大到小排序。(\(v_j\)的实际意义在于,将子树\(j\)的所有点连接到父亲上之后,父亲点权的增量)
对于一个儿子\(j\),如果\(s_j\geq 0\),则先递归处理这个儿子,再连接它与父亲之间的边。
否则,这个儿子无法自己处理子树中的边,需要先连接父亲与它的边,再递归处理子树,并将父亲剩余的权值传递下去。
正确性存疑的地方只有连接某个儿子时,由于减去了某条边的权值,权值和可能\(<0\)。
发现对于\(v_i\geq 0\)的点,连接后一定会使父亲的剩余权值增大,不会影响。
否则,此后的点\(v_i\)均为负。由于最后父亲剩余权值\(\geq 0\),则在这个不断减小的过程中也不会\(<0\)。
实现时,发现一个儿子的影响只和\(v_i\)的正负性有关,因此并不需要排序,只需扫两遍,先取\(v_i\geq 0\)的儿子,再取\(v_i<0\)的儿子即可。
复杂度\(O(n\log n)\),瓶颈在于求mst时的排序。
- C
\(6pts:\)
显然质数的答案一定是\(0\)。
\(34pts:\)
爆搜+打表,可以过掉\(n\leq 100\)。
\(51pts:\)
看到出题人完全平方,就很容易想到质因数异或线性基。
用bitset维护每个质数,复杂度\(O(\frac{n^4}{64\ln ^2n})\),实现优秀可过\(n\leq 1000\)。
\(100pts:\)
设\(g(x)\)为\(x\)向左找到的最近的数,即与\(f(x)\)意义类似,只是方向相反的函数。
发现\(f(x)\)与\(g(x)\)互为反函数。
证明:假设从\(f(x)\)向左找到的第一个位置为\(y>x\),则我们把两次找到的序列取对称差(即异或),则得到的新序列也是完全平方数,发现由于\(f(x)\)在两个序列里都出现了,且\(x\)只出现了一次,所以可以找到一个左端点为\(x\),右端点\(<f(x)\)的序列,与\(f(x)\)是向右找到最近的数矛盾。
也就是说,每个合数都有且仅有一个互不相同的解,且答案为\(g(x)\)。
考虑从\(x\)往前扫,每次加入一个\(l\),看是否线性无关即可。复杂度\(O(\frac{n^3}{64\ln ^2n})\),好像没什么用。
发现超过\(\sqrt n\)的质数只会有一个,在线性基上特判一下即可。
不超过\(1000\)的质数只有\(168\)个,复杂度\(O(\frac{168^2\times n}{128})\),由于对于实际上跑不满(比如答案不会超过\(\frac n2\)),所以可过。
原文地址:https://www.cnblogs.com/suwakow/p/11375082.html