zoukankan      html  css  js  c++  java
  • 历年NOI真题选做

    没啥水平,大家将就着看,帮忙催更哦~

    [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) 个质因数的方案数。

    转移:

    [f[i][j][k][0]+=f[i-1][j][k|s][0](j&s==0)\ f[i][j][k][1]+=f[i-1][j|s][k][1](k&s==0)\ f[i][j][k][2]=f[i][j][k][0]+f[i][j][k][1]-f[i-1][j][k][2] ]

    发现 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) 这种具有提示性的东西,我就向组合数上想了……

    大概过了半个多小时摸出来(结果萌神说可以用网格行走直接推)是:

    [frac{inom{n+i}{i} imes (n-i+1)}{n+1} ]

    嗯,不用写 (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] 骑行川藏

    题意

    一开始以为全程一个速度,把式子展开一看觉得可能无解,重新看题发现每段速度不一样……

    用数学语言描述这个题:

    [sum_{i=1}^n s_ik_i(v_i-v_i')^2 = E\ ans=min{sum_{i=1}^n frac{s_i}{v_i}} ]

    观察部分分发现会 (n leq 2) 可以获得 (40pts)(n=1) 的时候直接做,(n=2) 可以三分其中一个算另外一个。(我也不知道我哪里写挂了只有 (35)

    考虑每一段都可以花费一些能量来减少一些时间,也就是每一段都有一个性价比。根据木桶效应,最优时应该每一段的性价比一样。我们可以二分这个性价比求解。

    那么这个性价比怎么表示呢?当然是 (frac{Delta t}{Delta E}) 这样的形式。这个就是导数的基本思想了。

    为了方便我们把 (v) 作为变量,那么 (F(v)) 可以用 (frac{frac{dt}{dv}}{frac{dt}{dE}}) 表示。

    [t=frac{s}{v}\ t'=-frac{s}{v^2}\ E=sk(v-v')^2\ E'=2sk(v-v') ]

    然后可以二分导数,然后二分出导数为 (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) 出发,所需要的最小购票费用。

    [f_i=min_{x in anc_i,dis_i-dis_x leq l_i }{ f_x + (dis_i-dis_x) imes p_i + q_i} ]

    展开一下这个式子,移项:

    [f_i=min_{x in anc_i,dis_i-dis_x leq l_i }{ f_x -dis_x imes p_i} + dis_i imes p_i + q_i ]

    考虑两个点 (u,v) ,假设 (dis_u<dis_v) ,那么 (u)(v) 更优:

    [f_u-dis_u imes p_i < f_v -dis_v imes p_i\ f_u-f_v < (dis_u-dis_v) imes p_i\ frac{f_u-f_v}{dis_u-dis_v} > p_i\ ]

    如果这个不是在树上而是在序列上,可以随便维护一个单调队列就没了。

    [NOI2007] 生成树计数

    题意

  • 相关阅读:
    C语言基本快速入门教程
    几何深度学习前沿
    Anaconda 更改清华源
    大学安全教育-实验室安全测试题库
    《如何写好科研论文》(清华)慕课答案
    集群考试试卷
    集群考试相关
    Linux下tar压缩解压用法
    2020-安全微课(新生入学教育)答案
    函数用法和底层分析
  • 原文地址:https://www.cnblogs.com/Kylin-xy/p/NOI-try.html
Copyright © 2011-2022 走看看