20250725模拟赛题解
小凯的疑惑
题目来源:NOIP 2017 提高组 Day1 T1
题目链接:https://www.luogu.com.cn/problem/P3951
直接输出 \(ab-a-b\) 即可。
证明:不妨设 \(a < b\)。
考虑将所有数字按模 \(a\) 的余数分为若干组,第 \(i\) 组为模 \(a\) 余 \(i\) 的所有数。例如,\(a=5, b=7\) 时,第 0 组就是 \(5, 10, 15, \cdots\),第 2 组就是 \(2, 7, 12, \cdots\)。第 0 组只用 \(a\) 就能表示,后面就不考虑了。
引理1:每组如果有一个数可以被表示出来,则该组大于它的所有数均可被表示出来。
这个引理是显然的,只需要再多拿出来一枚面值为 \(a\) 的硬币即可。
引理2:非0组能被表示出来的最小数是 \(b\) 的倍数。
如果不是,那么它可以表示为 \(ax+by\),让 \(x\) 变 \(0\),则可表示出同组的数种更小的一个。
引理3:当 \(i > 0\) 时,第 \(i\) 组中前面若干个数无法表示,直到遇到第一个 \(b\) 的倍数。
由引理2显然得证。
引理4:\(b\) 的 \(1\) 倍、\(2\) 倍、\(\cdots\)、\(a - 1\) 倍分散在第 \(1, 2, \cdots, i - 1\) 组中。
如若不然,若在 0 组,则 \(xb=ya\),由 \(a, b\) 互素,\(y\) 必是 \(b\) 的倍数,从而 \(ya \ge ba\),\(x \ge a\),也就是说至少要到 \(b\) 的 \(a\) 倍才能进 0 组。如果有两个倍数进了同一组,那么它们的差是 \(a\) 的倍数,同理可得出,它们的差至少是 \(ab\),从而较大的那个倍数不会小于 \(ab\)。
综上,我们要找的就是 \(b\) 的倍数中,最大的不超过 \(ab\) 的数,然后取它所在组的上一个数。
显然结果是 \((a-1)b - a = ab - a - b\)。
最终时间复杂度 \(O(1)\),记得开 long long。
涂色游戏
题目来源:NOI 2023 春季测试 T1
题目链接:https://www.luogu.com.cn/problem/P9117
直接模拟显然会超时。考虑每个位置的染色规律,显然我们只用考虑最后一次它被染成什么色就可以了,所以过程中的变化我们不必关注。
用两个一维 pair<int, int> 数组存储每行、每列的染色记录(操作编号和染成的颜色),输出的时候,对于每个位置,取该行的最后染色记录和该列的最后染色记录,比较后即可得出结果。
时间复杂度 \(O(T(q + nm))\),毕竟每次询问再怎么说也得 \(O(1)\) 存一下。
括号树
题目来源:CSP-J/S 2019 提高级 Day1 T2
题目链接:https://www.luogu.com.cn/problem/P5658
考虑链上的情况,显然就是很简单的递推。记 \(lastans[i]\) 为 以 \(i\) 号位置结尾的子串中有多少个合法的括号序列。我们用栈模拟括号匹配,如果 \(i\) 处不是右括号或“是右括号但找不到左括号匹配”,那么结果为0,否则设它匹配的左括号位置为 \(j\),则 \(lastans[i] = lastans[j - 1] + 1\),最后 \(ans[i]\) 就是 \(lastans[i]\) 数组的前缀和。
考虑如何拓展到树上,不难想到在进行 DFS 的过程中维护这样一个栈,并更新结果数组。需要注意在 DFS 处理完每一个点之后,要对它造成的影响进行消除。如果这个位置没有匹配上,则确保把它自己弹出去;否则,要把匹配上的那个左括号加回来。最后,\(ans\) 数组不再是前缀和,而是自己父亲的 \(ans\) 加上自己的 \(lastans\)。
例如,父亲结点是左括号,有 2 个儿子,都是右括号,那么处理第 1 个儿子的时候,栈中的父亲左括号会弹出,因此处理完这个儿子后必须再把被弹出的结点压回来,不然下一个儿子就匹配不上了。
时间复杂度 \(O(n)\)。
赛道修建
题目来源:NOIP 2018 提高组 Day1 T3
题目链接:https://www.luogu.com.cn/problem/P5021
考虑二分答案,变成判定问题。
我们注意到,树上的链的形状都是从一个点先向上走,走到它的一个祖先后,再选择另一个子结点向下走。我们要求的是最多设计的赛道数,且已经转化为了判定问题,那么自然可以想到,如果一个很深很深的子树自己就形成了一条刚刚好满足要求的路径,那我们就没必要把这个路径拆了形成更浅的路径。毕竟,一个子树往上走,最多也只能参与到一条路径的构成中,结果不会变好。
考虑一个结点 \(x\),如果它是一个儿子全是叶子结点的结点,我们当前要判定的路径长度为 \(L\),那么我们就可以把所有叶子结点到它的距离排序,按照最小配最大的思路尽量多配对。配对之后,如果有剩余的儿子,我们选则一条长度最大的往上连。
但这里又有一个问题,就是贪心的时候可能把最大的选走了,而另一种解法是贪心的时候不让最小配最大,往往也能配出相同的对数。考虑 \(3,4,5,6,7\),限制为 \(9\),贪心会配出 \(3+7, 4+6\),但 \(3+6,4+5\) 同样可以满足要求,剩下的还是更长的边。
所以,我们在这一步贪心之后,还要加一步二分答案,求出可以保证结果不变的、可以剩下的最长的边。
对于这样的特殊结点,我们的贪心是正确的,那么对于其它结点,只需要把每个儿子传上来的结果加上到此儿子的距离,就可以转化成相同的情况了。总之,先二分答案转化为判定,然后使用贪心对每个子树进行求解,最后再加一步二分答案保证子树上传的结果最优。
时间复杂度 \(O(\log(nl) \times n \log(n))\)。
                    
                
                
            
        
浙公网安备 33010602011771号