T1~T3略过
T4 货币系统
首先考虑没有新面值的情况,可以知道所用的最小面值可以用下面的伪代码求出:
for i = 15 downto 1
ans += money / c[i]
money %= c[i]
这是一个贪心,因为原本的面值都是一个数字加几位0,所以money的每一位都分开计算,然后加起来就可以了,然后每一位都有1,2,5三种选择,那么每个数字对应的纸币数如下:
这里有一个规律,就是第二列的数字是第一列数字被1,2,5做整除和取模得到的。
接下来考虑新面值,我们因为新面值的面值没有原来面值的特殊性,所以我们采取暴力,枚举使用张数,最多使用50000张,然后剩下的用上面的程序求出使用个数,
T5 蜈蚣
题目这可以转变为:首先浪费掉可以浪费的袜子,然后满足每一条蜈蚣,然后每条蜈蚣分别浪费掉一些。
首先,对于一种颜色 i i i,如果 a i < F a_i<F ai<F,那么这种颜色的袜子要全部浪费掉。而如果 a i ≥ F a_i\ge F ai≥F,那么要浪费掉 F − 1 F-1 F−1只袜子,显然剩下 a i − F + 1 a_i-F+1 ai−F+1只。(接下来每次出现 a i a_i ai都表示剩下的袜子数,而不是题面的意思)
现在我们逐只蜈蚣进行分配,首先我们要在剩下数量最多的袜子中拿到一只,这样就可以满足一只蜈蚣,然后在剩下最多的颜色 p p p中浪费掉 min { a p , F − 1 } \min\{a_p, F-1\} min{ap,F−1},如果在浪费之前 a p a_p ap已经为 0 0 0,这样表明答案是无解,否则接着满足下一只蜈蚣。
T6 珠宝
本题使用状态压缩dp完成,不过在思考方程之前,我们要做一些有意思的思考。
首先看看这个样例:
其中小方块是同一种颜色,我们要将它们合并。用子问题的方式思考合并策略,我们可以发现有两种:
-
首先将第二个开始的所有珍珠放好,然后将第一个珍珠放入已经排好的序列中。
-
选取一段前缀保持不动,它的首尾都是这种颜色,然后将这段前缀中所有其他颜色的珍珠拿到后面合并,它们的处理方法和1.类似,都是将后面的其他颜色珍珠放好,接着将它们分别放好,然后将剩下的这种颜色的珍珠放入这段前缀之间。
这样相当于将原来的操作分为两部分:将珍珠拿出,放入一个假想的中转站,然后将步数 + 1 +1 +1;将这个珍珠从中转站中拿出,放入想放入到位置,步数不变。
现在我们来定义状态: f ( i , S ) f(i,S) f(i,S)表示原序列前 i i i个珍珠中选取颜色包含在集合 S S S中的所有珍珠,将他们排好。然后还有两个辅助的函数 s 1 c ( i , j ) s1_c(i,j) s1c(i,j),表示原序列前 i t o j i~to~j i to j中珍珠中颜色为 c c c的个数。 s 2 S ( i , j ) s2_S(i,j) s2S(i,j)表示原序列中前 i t o j i~to~j i to j个珍珠中颜色包含在集合 S S S中的个数。
显然,如果 i > n i>n i>n或者 S = N U L L S=\mathrm{NULL} S=NULL的时候 f ( i , S ) = 0 f(i,S)=0 f(i,S)=0.
对于剩下的情况,我们可以写出方程:
f ( i , S ) = { f ( i + 1 , S ) i f i ∉ S min { f ( i + 1 , S ) + 1 min i ≤ p , c p = c i { f ( p + 1 , S − c i ) + s 1 c p ( p + 1 , n ) + s 2 S − c i ( i , p ) } i f i ∈ S f(i,S)=\begin{cases} f(i+1,S)& if~~i\notin S\\ \min\begin{cases} f(i+1,S)+1\\ \min\limits_{i\leq p,c_p=c_i}\{f(p+1,S-{c_i})+s1_{c_p}(p+1,n)+s2_{S-{c_i}}(i,p)\} \end{cases}& if~~i\in S \end{cases} f(i,S)=⎩⎪⎪⎨⎪⎪⎧f(i+1,S)min⎩⎨⎧f(i+1,S)+1i≤p,cp=cimin{f(p+1,S−ci)+s1cp(p+1,n)+s2S−ci(i,p)}if i∈/Sif i∈S
有一点点长,但是理解起来其实困难不大。