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