没啥水平,大家将就着看,帮忙催更哦~
[NOI2013] 向量内积
观察发现暴力很足,可以直接 (O(n^2d))。
继续观察数据范围,发现 (K=2) 或 (K=3) ,(K=2) 可以用 (bitset) 无脑草过去,复杂度 (O(frac{n^2d}{w}))。
(K=3) 就魔改一下 (bitset)。考虑 (mod 3=0) 的设为 (0) 其余为 (1) ,剩下的应该是 (1 imes 2,2 imes 1,1 imes 1,2 imes 2 ,mod 3=2,2,1,1),就相当于少算了 (1 imes 2,2 imes 1) ,于是按照 (mod 3==2) 来补齐没算的。
直接枚举可能不太行,考虑随机打乱排列大概有 95 ,剩下的 5 分 reverse 一下排列就能得到。稍微判断一下(但是在考场上我可能只能搞到95)。
[NOI2016] 区间
类似于今年省选 A 卷 D1T1,就是不断往后加到合法,前面每次往后退一个。
[NOI2013] 快餐店
考虑一棵树,一定是最长链某个位置劈开。
现在是个基环树,考虑最长路径不经过环,那就把环劈了,找环上某个点,使得离这个点最远的子树距离最小。
这个可以把环拉开然后根据子树距离排一下,统计前后缀 max
计算答案。
但是可能最优位置不在环上,那我们还得把某两个点在环上的距离加上,就是计算的时候我们要算链长,环上距离长,子树深度。
统计的时候就是枚举环上某一个点 (i),更新 (min(max() (i) 子树最大深度 (+i) 之前的链长 (+i) 之后的链长,(max() (i) 前面两个点 (u,v) 的最大深度 (+(u,v)) 在环上的距离,(i) 后面两个点 (u,v) 的最大深度 (+(u,v)) 在环上的距离 ())))
细节有点多。
[NOI2015] 寿司晚宴
怀疑我打过的这种套路的模拟赛都是从这题衍生来的。(你谷月赛,校内 NOIp 模拟赛)
考虑两个数不互质说明它们有公共的质因数,考虑 (n leq 30) 一共只有 (10) 个质因数可选,于是可以设 (f[s1][s2]) 表示第一个数选的因数集合是 (s1) ,第二个数选的因数集合是 (s2) 。那么 (f[s1|i][s2]+=f[s1][s2](i&s2==0),f[s1][s2|i]+=f[s1][s2] (i&s1==0)) ,由于 dp
的时候数组值会改变所以要滚一下不能直接修改原数组(两个数组互相转移)。
然后发现可以按照 (leq sqrt{n},gt sqrt{n}) 来分类质因数,因为 (gt sqrt{n}) 的质因数最多只有一个。
那么就是 (leq 22) 的质因数 (2,3,5,7,11,13,17,19) 和 (gt 22) 的质因数。我们可以把每个数预处理一下,算出来它最大的质因数是多少,排个序,然后状压 dp
。
设 (f[i][j][k][0/1/2]) 表示前 (i) 个质因数中,第一个数选的小质数集合为 (j) ,第二个数选的小质数集合为 (k) ,两个人都没选 / 第 (1/2) 个人选了 第 (i) 个质因数的方案数。
转移:
发现 dp
的时候可以类似 (01) 背包那样从后往前枚举,这样可以省掉一维。
想的时候有点细节,写起来很舒适。
[NOI2018] 冒泡排序
发现 (O(n^2)) 有 (80pts) 的高分,就先去想了 (O(n^2)) 做法。
首先写一个暴力,打表长度为 (n) 以 (i) 开头的合法排列个数:
1
1 1
2 2 1
5 5 3 1
14 14 9 4 1
42 42 28 14 5 1
132 132 90 48 20 6 1
诶,觉得第一项好眼熟啊……萌神在我右边看了一眼,说:“不会吧不会吧不会真有人不会卡特兰数吧?”
卡特兰数是 (frac{inom{2n}{n}}{n+1}) ,于是我有了大胆猜想,把每一项都 ( imes (n+1)) ,看到是这个东西:
1
2 2
6 6 3
20 20 12 4
70 70 45 20 5
252 252 168 84 30 6
924 924 630 336 140 42 7
3432 3432 2376 1320 600 216 56 8
12870 12870 9009 5148 2475 990 315 72 9
本来卡特兰数就有组合数,加上 (20,45,252) 这种具有提示性的东西,我就向组合数上想了……
大概过了半个多小时摸出来(结果萌神说可以用网格行走直接推)是:
嗯,不用写 (O(n^2)) 了,这个柿子可以预处理组合数 (O(1)) 计算。
考虑计算大于某排列字典序的排列个数,可以逐位计算大于它的排列个数,就是以大于它的数开头的排列个数,每一位依次算下去。
所以这个也是一样的道理,但是要扣掉一些不合法的,就是往后走的时候要把当前这个数减去比他小的数的个数,然后到某个位置不合法了就跳出,细节很多。
用网格行走推:
首先有个结论:最长下降子序列的长度不能超过 2。
证明可以看这个 ,感觉有点麻烦(我考场上肯定证不出来啊!)。
然后设 (dp[i][j]=) 选了 (i) 个数放入序列最大值为 (j) 的方案数, (j) 可以转移到比 (j) 大的,由于最长下降子序列长度不能超过 2 ,所以只能向未选的最小值选,那么 (f[i][j] ightarrow f[i+1][j+k] (j+kleq n,k geq 0)) ,我们把 ((i,j)) 抽象成一个点,实质上就是求 ((0,0) ightarrow (n,n)) 且不跨过 (y=x) 而且在它上面的,只能向上向右走的方案数(实际上这就是卡特兰数)。有了字典序的限制,可以考虑按照数位 dp 的方式一步步找限制,到某个地方超过限制了就跳出。
[NOI2019] 弹跳
(1 sim 8 :) 暴力连边 (+) dij
(9 sim 13 :) 离线预处理 (+) 暴力连边 (+) dij
(14 sim 18 :) 线段树优化建图 (+) dij
随手写写拼拼就好了,所以我在考场大概只有暴力分……
考虑满分做法就是把一维的线段树优化建图搞到二维上去,直接二维线段树优化建图会被卡空间(卡得特别严重,吐了,不知道出题人什么心态啊),然后膜了膜题解(参考)
发现空间限制的瓶颈在于边比较多,由于 dij
的时候每个点都会只会更新一遍,考虑不直接连边,先把里层的建出来,然后对于外层的可以按照最短路的扩展方式,每次加边的时候就更新这一段的最短路,并且把更新过的区间加入队列中。这样就可以避免卡空间了,最大的点用了 123 MB 左右。(不带注释一共 4.73K,168行……)
[NOI2018] 归程
(1sim 4,6sim 9,15,16:) 有一个很显然的暴力,就是先预处理所有点到终点的最短路(建反图跑一遍),然后每次根据水位线建出车子可以走的图,做一遍 dij
,再枚举从哪个点下车是可行的而且路径最短,更新答案。时间复杂度 (O(nQ)) ,期望得分 (50) 。
(5:) 海拔只有一种,要么都能选要么都不能选,可以直接判断能不能走,(ans=0) 或 (dist[n]) ,期望得分 (5) 。
(10,11:) 考虑一条链的情况:存在某条边有积水,在这里必须下车,每次只要找到 (1sim n) 的路径上第一条有积水的边就可以了,实际上可以预处理这条路径的前缀 min
,由于这个是单调不增的可以二分。由于链的包和暴力重合,所以链应该是对树有提示的。那么考虑树上某个点,我们可以走到这个点,然后从这个点下车走到终点,还是可以预处理终点到每个点的最短路,由于每个点到出发点的路径是唯一的,所以可以预处理路径最小值,每次找 (min geq) 水平面的且距离最短的,可以根据路径上的min
排序之后做后缀 max
解决。期望得分 (10) 。
(12,13,14:) 不强制在线可以把水位线排序,由于每次只会加边,所以可以先预处理最短路,每加一条边更新一下答案,就是加进来之后和 (1) 相连的连通块里的路径长度最小值。期望得分 (15) 。
所以比较正常的暴力大概有 (80) 。(写正解但是用了 spfa 的似乎没这个分……)
考虑正解:kruskal 重构树。树上某条 (i ightarrow j) 的边表示图上 (i ightarrow j) 的路径上边的最小值,这样根到任意一个点路径上的边权是递增的。由于根到 (fa[i]) 的距离比根到 (i) 的距离大,所以建树的时候用并查集维护,对于每条边 ((u,v,w)) ,如果 (v) 到根的距离比 (u) 大说明 (v) 是 (u) 的祖先,那么就连一条 (v ightarrow u) 的边。这棵树相当于并查集不路径压缩的状态,可以直接倍增跳,由于边权是降序的,所以跳到最后就是海拔高度。
[NOI2017] 游戏
上来看到这种东西: 若在第 (i) 场使用型号为 (h_i) 的车子,则第 (j) 场游戏要使用型号为 (h_j) 的车子。
这就是一个选了 (i) 就要选 (j) 的限制。
发现场地有 x a b c
四种,特别是这个 x
很麻烦,但看到有一半 (d=0) 的,所以先考虑 (d=0) 。
现在每种场地只能用 2 种车子,令 (i) 表示用第一种车,(i') 表示用第二种车,分类讨论一下:
-
(i) 号场地不能用 (h_i) : 不用管这个条件
-
(i) 号场地可以用 (h_i) 但 (j) 号场地不能用 (h_j) : 连边 (i ightarrow i') 表示如果用了一定无解
-
(i) 号场地可以用 (h_i) , (j) 号场地可以用 (h_j) : 连边 (i ightarrow j , j' ightarrow i') 表示如果用了 (i) 一定要用 (j) ,如果没用 (j) 一定不用 (i) 。
然后缩点,dfs,找 scc ,如果 (i) 和 (i') 在同一个 scc 肯定无解,否则把缩点后的图拓扑排序,如果 (i) 的拓扑序在 (i') 之后,说明 (i) 用第一种可用的,否则用第二种。这样可以获得 (45) 分的好成绩。
再考虑 x
,发现并不会 3-SAT
。
我们发现 x
非常少,只有 (8) 个。我们可以暴力枚举每个 x
适合哪两种赛车,这样是 (3^d) ,还有 (20) 分拿不到。
注意到我们枚举适合的赛车 AB AC BC
,就是 x=a / x=b / x=c
,其实我们已经尝试 “这个位置能否选 A B C
” ,所以可以任意去掉一种情况不要再尝试了。
这时候时间复杂度被降低到 (O(2^d(n+m))) ,可以通过本题。
数据太垃圾了,只有 #9 #10
有一丢丢强度,我清空写错了都有 (90pts) ……
[NOI2012] 骑行川藏
一开始以为全程一个速度,把式子展开一看觉得可能无解,重新看题发现每段速度不一样……
用数学语言描述这个题:
观察部分分发现会 (n leq 2) 可以获得 (40pts) , (n=1) 的时候直接做,(n=2) 可以三分其中一个算另外一个。(我也不知道我哪里写挂了只有 (35))
考虑每一段都可以花费一些能量来减少一些时间,也就是每一段都有一个性价比。根据木桶效应,最优时应该每一段的性价比一样。我们可以二分这个性价比求解。
那么这个性价比怎么表示呢?当然是 (frac{Delta t}{Delta E}) 这样的形式。这个就是导数的基本思想了。
为了方便我们把 (v) 作为变量,那么 (F(v)) 可以用 (frac{frac{dt}{dv}}{frac{dt}{dE}}) 表示。
然后可以二分导数,然后二分出导数为 (mid) 时的最优答案。
在洛谷上一直 (85) 显示我输出 -nan
,卡了一个小时,去 loj 下数据发现没错,结果交到 loj 上过了??垃圾洛谷!
[NOI2017] 整数
暴力就是按题意来,直接模拟。
但是发现修改的位置连续性没有那么强,是一段一段修改的,可以用 set
维护一下最近的要改的位置,每次修改的复杂度就是 (log) 的。
[NOI2019] 机器人
最基础的暴力有 20。
考虑稍微有点技术含量的,(B_i leq 10^4) :设 (F[l][r][x]=) 现在的区间是 ([L,R]) ,这个区间最高的柱子是 (x) 的方案数。我们枚举最大值所在的点 (K) ,那么 (F[l][r][x]=sum_K sum_{yleq x} F[l][K-1][y] imes F[K+1][r][y-1]) 。
发现 (300 imes 300 imes 10^4) 会爆空间,但是仔细思考会发现很多状态是可以剪枝的,所以把每个区间 ([l,r]) 编上号,冗余状态剪掉,只管有值的状态,这样可以获得 (50pts) 。
看到 (A_i=1,B_i=10^9) ,觉得应该有某种规律,应该是一个可以被插出来的多项式,那么正解也往多项式上想。
我们发现当 (l=r) 时,dp 状态是一个多项式 (x^0) ,前缀和是 (x^1) ,拓展合并后的多项式,发现 ([l,r]) 的 dp 前缀和是 (r-l+1) 次多项式,然后插值。
考虑 APIO2016 划艇 的套路,把每个区间 ([a_i,b_i)) 离散化下来,拆开,这样我们只需要 dp 每一段区间 ([L,L+n)) ,对每个 dp 状态的前缀和进行插值。同时求出其在 (L_{i+1}-1) 处的值,再做下一段即可。
因为下标连续所以可以线性插值。时间复杂度 (O(n^2m)) 。
[NOI2014] 购票
考虑 dp ,(f_i) 表示从 (i) 出发,所需要的最小购票费用。
展开一下这个式子,移项:
考虑两个点 (u,v) ,假设 (dis_u<dis_v) ,那么 (u) 比 (v) 更优:
如果这个不是在树上而是在序列上,可以随便维护一个单调队列就没了。