转自 http://bestcoder.hdu.edu.cn/blog/
1001. Add More Zero
答案就是 ⌊log10(2m−1)⌋ ,注意到不存在 10k=2m ,所以 ⌊log10(2m−1)⌋=⌊log102m⌋=⌊mlog102⌋ ,这样做的时间复杂度是 O(1) 。
1002. Balala Power!
每个字符对答案的贡献都可以看作一个 26 进制的数字,问题相当于要给这些贡献加一个 0 到 25 的权重使得答案最大。最大的数匹配 25,次大的数匹配 24,依次类推。排序后这样依次贪心即可,唯一注意的是不能出现前导 0。
1003. Colorful Tree
单独考虑每一种颜色,答案就是对于每种颜色至少经过一次这种的路径条数之和。反过来思考只需要求有多少条路径没有经过这种颜色即可。直接做可以采用虚树的思想(不用真正建出来),对每种颜色的点按照 dfs 序列排个序,就能求出这些点把原来的树划分成的块的大小。这个过程实际上可以直接一次 dfs 求出。
1004. Division Game
显然每个石子堆最多做
∑mi=1ei
(记为
w
)次操作。此外,如果定义一个堆做
为了统计结束于石子堆
i
的情况数,我们可以枚举这是它第几次操作时结束的,不妨设为
我们可以基于一个数的不同质因子几乎互不影响的观察得到第一个结论。每次操作保证任何一个 ei (ei>;0) 可以减少且至少一个 ei 会减少。自然而然我们可以发现一个容斥关系。
考虑
f(x)
的组成,不妨设在某种方案中第
j
次操作使
假设只满足第一个条件的相应方案数为
g(x)
,我们可以发现每个
i
分别对应一个组合问题,从而是有
我们也可以观察到如果某些
j
与第二个条件产生了矛盾,与之相关的
总时间复杂度为 O(w m + wlogn + w k),然而实现上谨慎一些也是很有必要的。
1005. Expectation Division
解决这道题需要观察到一些比较经典的结论。在分析前我们先两组与题目相关的定义:对于任意正整数的质因子分解
n=∏ki=1peii
,定义
ω(n)=k
表示
n
的不同质因子个数,
这题本来是为 OI 赛制的比赛准备的,然而没有被使用。接下来会根据几个部分分给出做法,希望能对大家有所启发。
对于 n≤106 的数据:
题目中所表述的过程是一个标准马尔可夫过程,所以我们可以用
f(n)
表示使用这种操作把
n
变成
很容易计算出满足 n∈N+, n≤N 的所有 f(n) ,复杂度为 O( ∑n≤Nσ(n))=O(NlogN) ,这里不再赘述。
对于 n≤1012 的数据:
直接在线为每个询问计算答案是有些不现实的,这里给出一个考虑不同数字之间的关系并记忆化存储信息的做法。
首先观察到,对于 n=∏ki=1peii, m=∏k′i=1p′ie′i ,如果 k=k′ 并且对于 i=1,2,⋯,k 都有 ei=e′i (适当地安排质因子的顺序之后),那么我们可以得到 f(n)=f(m) ,这与具体的 pi,p′i 是多少无关。
不妨将每个数字对应的
e1,e2,⋯,ek
按非升序排序,可以观察到将这些幂指数的集合拿出来并去重后剩下集合的数量不会很多。对于一个集合
e1,e2,⋯,ek
(满足非升序),我们可以构造出可能的最小值
n=2e13e25e37e4⋯
,而且可以大致估计出不超过
N
的本质不同的幂指数的集合个数不会超过
事实上当
n≤1012
时,我们可以观察到
σ(n)≤6720
,于是每次询问时将
n
映射到其幂指数的集合上,利用记忆化搜索的技巧枚举约数即可以单次 O(
对于 n≤1018 的数据:
之前的方法难以奏效,因为现在有 σ(n)≤103680 并且本质不同的集合个数达到 32749 个。
为了观察更细致一些,我们定义 g(n)=∑d|nf(d) ,记忆化搜索时先计算出满足 d|n,d<;n 的所有 f(d),g(d) ,然后依次计算出 g′(n)=∑d|n,d<;nf(d), f(n)=σ(n)+g′(n)σ(n)−1, g(n)=g′(n)+f(n) 。
尝试优化计算 g′(n) 的过程,也即计算中的瓶颈部分。如果改用容斥的技巧,我们有 g′(n)=∑T⊆S(−1)|T|+1g(n∏pi∈Tpi) ,其中 S={pi|i=1,2,⋯,k} ,这样可以使单次运算的复杂度从 O(σ(n)) 降到了 O(2ω(n)) 。
类似地,当 n≤1018 时,我们可以观察到 ω(n)≤15 ,所以这个优化在实际运算中已经足以通过 n≤1018 的数据。
[b]对于 n≤1024 的数据:[/b]
上述做法再次不适用了,因为现在本质不同的集合个数达到 172513 个,并且有 2ω(n)≤218≤262144 ,因此我们需要再次进行优化。
考虑
g(n)
的组成,所有满足
d=∏ki=1piti
且对于
i=1,2,⋯,k
有
0≤ti≤ei
的
d
都会对
参考大小为
注意这个做法具体结合到非升序的幂指数序列时可能要修改一下 gx(n) 的定义。
复杂度分析:
这道题的大数运算很容易在常数时间内实现。记忆化搜索时可以用 bitset 配合基数排序线性地对幂指数序列的排序,但是它是可以避免的(甚至是递归时的拷贝)。标程的时间复杂度与空间复杂度都是
O((S(N)+T)ω(N))
,其中
S(N)
表示在不超过
N
的正整数里出现的本质不同的集合个数
1006. Function
考虑置换
a
的一个循环节,长度为
那么
f(i)
的值在置换
b
中所在的循环节的长度必须为
而如果 f(i) 的值确定下来了,这个循环节的另外 l−1 个数的函数值也都确定下来了。
答案就是
∑ki=1∑j|lij⋅calj
改为
∏ki=1∑j|lij⋅calj
,其中
k
是置换
时间复杂度是 (n+m) 。
1007. Gear Up
整个图的结构是一个森林,首先可以将共轴的齿轮看成一个块(它们角速度相同),再考虑共边的情况。
如果
x
和
由此可以得出每个连通分量中每个齿轮角速度与某个特定齿轮的关系,从而利用线段树维护齿轮(或块)的 dfs 序列对应的区间角速度最大值。具体来说,每个连通分量任选一个齿轮作为参照点,维护其他齿轮与其角速度的差值。每个连通分量可以看成是一棵有根树,当一个齿轮的半径发生变化时,根据其是 rx 还是 ry 分两种情况更新一段 dfs 序区间。查询时只需要得出对应连通分量中相对角速度的最大值,再与当前点的相对角速度进行对比即可算出实际的最大值。
具体实现中可以维护 log2ω ,在输出时再转化为 logω 。
1008. Hints of sd0061
最慢的情况是
b
的取值为
从最大的取值到最小的取值依次使用近似线性复杂度的求第
k
小的方法即可,该方法的思想与快排相似,可以保证前
1009. I Curse Myself
由于图是一个仙人掌,所以显然对于图上的每一个环都需要从环上取出一条边删掉。所以问题就变为有
M
个集合,每个集合里面都有一堆数字,要从每个集合中选择一个恰好一个数加起来。求所有的这样的和中,前
对所有集合两个两个进行合并,设当前合并的集合是
A
和
事实上存在一个时间复杂度 (MK) 直接暴力求解的算法,但需要空间复杂度较好,例如空间复杂度 (K) 。
1010. Journey with Knapsack
标程的做法是生成函数。定义装满
k
体积空间的食物有
根据乘法原理,第
由于
0≤a1<;a2<;⋯<;an
的限制,我们知道对于
i=1,2,⋯,n
有
ai≥i−1
,也即
(ai+1)i≥i2
。所以只有
(n‾√)
项
(1−z(ai+1)i)
在模
z2n+1
意义下不为
1
。你可以利用类似背包的动态规划
剩下的部分是
(∏i=1n11−zi)modz2n+1
,这很像分拆数的生成函数。分拆数的生成函数被定义为
P(z)=∑k≥0p(k)zk
,其中
p(k)
表示
k
的本质不同的拆分数量。五边形数定理表明
回到原来的部分,我们做如下化简:
上面的式子表明我们可以利用前缀和将其规约到 P(z)modz2n+1 。总的时间复杂度为 (nn‾√) 。
1011. KazaQ’s Socks
找规律即可。规律是 1,2,⋯,nn numbers, 1,2,⋯,n−1n−1 numbers, 1,2,⋯,n−2,nn−1 numbers, 1,2,⋯,n−1n−1 numbers, 1,2,⋯,n−2,nn−1 numbers, ⋯ 。
1012. Limited Permutation
根据 [li,ri] (1≤i≤n) ,我们可以尝试线性地排序并建立一棵笛卡尔树,如果产生矛盾则答案为 0 。
具体来说,我们可以依次找到能够覆盖整个区间
若存在一棵笛卡尔树,则这棵笛卡尔树是唯一的。每棵子树都基于相似的子问题,所以我们只需要在合并子树时计算子树的组合即可。例如
u
有两个儿子
由于使用基数排序,故处理的时间复杂度为 (n) ,主要时间还是花在了读入上面。我们可以加一些读入优化使得复杂度变成 (nlog10n) ,其中 log10n≤6 。