NOIP 2018 原题重做
DAY 1
记忆尤为深刻的一场考试
T1-铺设道路(road)
算法 1(标准做法)
标准Codeforces Div2B难度。
把原题想成是用最少的1×D(?D∈[1,+∞))1\times D(\forall D\in[1,+∞))1×D(?D∈[1,+∞))的水平木板覆盖完整个直方图。
考虑现在铺第iii个水平位置,那么如果上一个水平位置在直方图内,即可直接将木板延长一次。
因此总的答案就是∑i=1nmax?(hi?hi?1,0)\sum^n_{i=1}\max(h_i-h_{i-1},0)∑i=1n?max(hi??hi?1?,0)
算法 2(笛卡尔树)
笛卡尔树模板题,答案就是笛卡尔树的带权sizsizsiz。
算法 3(线段树)
无脑找最小值然后区间减,分治直接做即可。
复杂度最极端是即为直方图表现为1…n1\dots n1…n的情况。
此时复杂度为∑i=1nlog?i=log?i!\sum^n_{i=1}\log_i=\log i!∑i=1n?logi?=logi!。
随便放缩一下就可以得到它上限为O(nlog?n)O(n\log n)O(nlogn)。
然而我们也可以用斯特林公式证明O(log?n!)=O(nlog?n)O(\log n!)=O(n\log n)O(logn!)=O(nlogn)。
T2-货币系统(money)
算法 1(标准做法)
显然答案是原货币系统的一个子集,那么我们需要删去一些面额。
我们被删去的面额显然满足它能用较小的面额的货币表示出来。
因此按货币从小到大完全背包即可。
算法 1 plus(拟阵)
其实原问题是一个很经典的拟阵形式,我们只需要证明它是一个拟阵我们就能完全严谨的证明算法1的结论了。
证明如下:
算法 2(同余最短路)
虽然复杂度不优秀,但是思路挺巧妙的。
首先将货币系统aaa按面值排序。
我们建a1a_1a1?个点分别表示modai=k\mod a_i=kmodai?=k的点。
对于每个ai(i>1)a_i(i>1)ai?(i>1),连一条xxx到(x+ai)moda1(x+a_i)\mod a_1(x+ai?)moda1?,权值aia_iai?的有向边。
对这个图求出源点为000到每个点的最短路did_idi?。
这个did_idi?的含义其实就是货币系统aaa能表示的最小的k(kmoda1=i)k(k\bmod a_1=i)k(kmoda1?=i)。
容易得到满足条件的货币系统的did_idi?与aaa货币系统的did_idi?一致。
因此我们只需要找原图的一个边数种类最小的联通子图即可。
看起来比较困难,其实我们只需要做最短路时尽量保留较小的边即可。
算法 3(生成函数)
显然有一个做法:
F(x)=∏i=1nGi(x)F(x)=\prod^n_{i=1}G_i(x)F(x)=i=1∏n?Gi?(x)
Gi(x)=∑j=0+∞xvi?jG_i(x)=\sum^{+∞}_{j=0}x^{v_i·j}Gi?(x)=j=0∑+∞?xvi??j
复杂度:O(TnMlog?M)O(TnM\log M)O(TnMlogM)。
然而NTT常数很大会T。
考虑换底,然后化简:
F(x)=e∑i=1nln?Gi(x)=e?ln?(1?xvj)F(x)=e^{\sum^n_{i=1}\ln G_i(x)}=e^{-\ln(1-x^{v_j})} F(x)=e∑i=1n?lnGi?(x)=e?ln(1?xvj?)
将eee上面的然后求导再积分回来:
?∫ln?′(1?xvj)d(1?xvj)=∫vjxvj?111?xvjdx=∫vj∑i=0+∞xvj(i+1)?1dx(等比数列公式)=∑i=0+∞x(i+1)vj(i+1)=∑i=1+∞xivji-\int \ln'(1-x^{v_j}) \mathrm{d}(1-x^{v_j}) \\=\int v_jx^{v_j-1}\frac{1}{1-x^{v_j}} \mathrm{d}x \\=\int v_j\sum^{+∞}_{i=0}x^{v_j(i+1)-1}\mathrm{d}x(等比数列公式) \\=\sum^{+∞}_{i=0}\frac{x^{(i+1)v_j}}{(i+1)} \\=\sum^{+∞}_{i=1}\frac{x^{iv_j}}{i} ?∫ln′(1?xvj?)d(1?xvj?)=∫vj?xvj??11?xvj?1?dx=∫vj?i=0∑+∞?xvj?(i+1)?1dx(等比数列公式)=i=0∑+∞?(i+1)x(i+1)vj??=i=1∑+∞?ixivj??
设H(x)=∑i=1+∞xivjiH(x)=\sum^{+∞}_{i=1}\frac{x^{iv_j}}{i}H(x)=∑i=1+∞?ixivj??,答案即为eH(x)e^{H(x)}eH(x)中能被表示的方案数为000的数的个数。
求出H(x)H(x)H(x)复杂度是调和级数O(Mlog?M)O(M\log M)O(MlogM)的,expexpexp也是O(Mlog?M)O(M\log M)O(MlogM)的。
因此复杂度:O(TMlog?M)O(TM\log M)O(TMlogM)。
然而它还是过不了。
T3-赛道修建(track)
算法 1(标准做法)
显然对答案进行二分,这样我们就转化为了求最多的划分链个数。
我们尝试用DFS的思路求解。对于一个节点,显然它的每个儿子都至多有一条未处理完的顶部为这个儿子的链。对于当前层,要么我们选出两条链连在一起,要么这条链成为当前点的未处理链。
显然我们可以在里面再套一个二分或者vector来做。
然而当时我不敢写二分套二分写了个双指针挂成80。