问题其实就是要你把 1 ∼ n 1sim n 1∼n 分成 k k k 段,最小化每一段的 c c c 值的和。
首先我们会想到,如果区间 [ l , r ] [l,r] [l,r] 中不存在两个有倍数关系的数,即 r < 2 l r<2l r<2l,那么 c ( l , r ) c(l,r) c(l,r) 就会取最小值 r − l + 1 r-l+1 r−l+1。
也就是说,如果我们按 [ 1 , 1 ] , [ 2 , 3 ] , [ 4 , 7 ] , [ 8 , 15 ] . . . [1,1],[2,3],[4,7],[8,15]... [1,1],[2,3],[4,7],[8,15]... 这样的方式去分段,那么只需分 log n log n logn 段即可把答案取到最小值 n n n,而且答案关于段数单调不增。
所以我们只需要考虑
k
<
log
n
k 考虑设DP状态
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示把
1
∼
i
1sim i
1∼i 分成
j
j
j 段时的最小答案,转移需要枚举分的最后一段是多少,复杂度不可通过。 考虑加速这个过程,观察式子: 这个做法的复杂度是
O
(
n
log
3
n
)
O(nlog^3n)
O(nlog3n) 的,比正解多一个
l
o
g
log
log,但是zkw线段树随便过。
c
(
l
,
r
)
=
∑
j
=
l
r
∑
d
≥
l
,
d
∣
j
∑
i
=
1
j
d
[
gcd
(
i
,
j
d
)
=
1
]
=
∑
j
=
l
r
∑
d
≥
l
,
d
∣
j
φ
(
j
d
)
c(l,r)=sum_{j=l}^rsum_{dge l,d|j}sum_{i=1}^{frac{j}{d}}[gcd(i,frac{j}{d})=1]=sum_{j=l}^rsum_{dge l,d|j}varphi(frac{j}{d})
c(l,r)=j=l∑rd≥l,d∣j∑i=1∑dj[gcd(i,dj)=1]=j=l∑rd≥l,d∣j∑φ(dj)
我们可以想到用线段树维护最小的DP值,每次枚举
i
i
i 的因子然后用预处理出的欧拉函数做一个前缀加操作,查询就直接查前缀最小值即可。#include


![[CF1603D] Artistic Partition——欧拉函数,线段树优化DP [CF1603D] Artistic Partition——欧拉函数,线段树优化DP](http://www.mshxw.com/aiimages/31/779113.png)
