前言:最近把历年的NOIP真题肝了一遍(还有3个紫题先咕掉了),主要是到1998年的提高组的题。把题目的做题简要思路搁在这儿,一个是为了考前翻一翻,想想自己的哪些思路要梳理的什么什么的,反正怎么说呢,就是一个备忘吧。目前整理到2013年了,再往前面的一些题思路不是很清晰(题意就tm不清晰怪我喽),见谅。
咕咕掉的题:NOIP2017宝藏,NOIP2017列队,NOIP2016宝藏。
咕咕的原因:心理阴影。(笑)
NOIP2017
小凯的疑惑
a*b-a-b
,写过题解的题,注意浪浪
时间复杂度
大模拟,先编译,后计算时间复杂度
编译先查F、E匹配,后插变量名重复
计算时候判断是不循环的,常数和n到n的,常数到n的
注意局部数组要先memset后使用,(我考场上AC了,洛谷上一直是WA一个点发现局部数组没有memset)
三种处理方式
逛公园
先从终点开始跑一遍dij,求出所有点到终点的距离
然后记忆化搜索search(x,key)代表从x开始跑可以多跑key的方案数
枚举接下来走哪条边,通过这个点到终点的距离与这条边指向的点到终点的距离的差来计算这条边多走的路程,让key减去他
标记一下vis[x][key]
,如果之前走过了这里就说明存在0环输出1退出就行
奶酪
并查集或搜索,注意浪浪
宝藏
模拟退火???
列队
没做
NOIP2016
玩具谜题
依稀记得是NOIP2017前我做的练手题。。。
模拟就行了,可以用异或处理方向,记得取模时候别弄错了,多造几组数据
天天爱跑步
没做
换教室
概率dp,先floyed一下多源最短路,然后f[i][j][0/1]
代表到第i次课用了j次权限,其中第i次课用了没用权限的,转移方程写法特别艰辛,还要注意如果j==0,第三维度的1直接是inf
最后从所有的f[n][i][0/1]
中找答案,最小值
边界是f[1][0][0]=f[1][1][1]=0
,别的初始化为inf
组合数问题
求前n行前m列杨辉三角中%k=0的数,直接前缀和就行了
蚯蚓
单调队列思想,先sort,然后维护三个队列,原队列,切开后长度较短蚯蚓队列,切开后长度较长蚯蚓队列,将第一个队列sort后,每次取出最长的切,因为你取出的最长的蚯蚓(在不延长的情况下)会越来越短,所以后两个队列也是单调递减的,每次取出队列中最长的蚯蚓切成两段,注意不用吧所有蚯蚓伸长长度,因为你可以通过时间算出当前蚯蚓的长度。然后最后输出的时候加上时间。
愤怒的小鸟
从我的题解粘过来,所以比较多
状压dp。
我们令f[k]
表示当前的状态为k所需要的最小的抛物线数,其中k是压缩后的状态,其中k的第i位为1表示第i个小猪被消灭掉了,为0表示没有消灭掉。初始状态为f[0]=0
,最终状态为f[(1<<n)-1]
我们枚举每一对猪来确定合法的抛物线,计算过原点和这两只猪的抛物线是谁。注意要特判两点,如果这两只猪的横坐标相同(根本就无法算出一个合法的抛物线啊),或者是抛物线的(a>0),那么我们就扔掉。抛物线的计算就是加减消元,注意无解的情况,然后把所有猪带入抛物线看那些符合
然后我们按照数字大小从小到大枚举所有状态,再用所有的抛物线去轰炸这个状态,假设这个状态为k,这个抛物线能消灭的猪是st,那么用这个抛物线消灭之后变成的状态就是k|st
,其中|
是按位或运算。dp方程为f[k|st]=min(f[k|st],f[k]+1)
。
最后f[(1<<n)-1]
就是答案
NOIP2015
神奇的幻方
模拟题,注意处理下一个位置的时候各种特判。各种各样的特判~~~
信息传递
基环树~首先是注意像这种基环树最好把单链递归改成循环处理,否则会炸。(想一想gxz的那个)
还有一个坑点是只有一个点没有被删除才开始统计环!注意
斗地主
要有很好的思考能力,注意到除了单顺子,双顺子,三顺子要搜索以外,如果把这三个扔了,可以直接贪心求出当前牌的数量。所以我们搜索只需要搜索当前单双三顺子,其它贪心即可。
注意枚举顺子的时候的一些坑点,比如只能到2,另外要逆着思路自己出几个数据试一下。
跳石头
很不错的二分答案题。注意二分答案以后不要写递归了。二分答案容易写错的是当前的中点是左偏还是右偏的(可以用长度为2的区间思考一下),还有判断的时候的各种细节问题。
子串
一个dp题,f[i][j][k][0/1]
代表的是当前A串到i,B串到j,匹配了k个字符串,最后一位是否匹配上的方案总数。f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]
和f[i][j][k][1]=(a[i]==b[j])*(f[i-1][j-1][k][1]+f[i-1][j-1][k-1][0]+f[i-1][j-1][k-1][1])
。第一个意思是这个不匹配,上一个可以不匹配或匹配,反正街上。第二个是这个要想匹配必须让两个字符相等,如果相等,那么可以接上上一次匹配的,也可以上一次不匹配这一次匹配,也可以上一次匹配了这一次另起炉灶。边界条件是所有f[i][0][0][0]=1
。最后答案是f[n][m][k][0]+f[n][m][k][1]
。这么做时间复杂度过去了,空间复杂度过不去,因为所有的i和所有的i-1有关我们开滚动数组。
注意取模1e9+7,还有最好要开long long。
这一类区间上的"续命式"的dp题,一般都会加一个大小只有2的维度,用来标记最后一位的状态,很有用。
NOIP2014
生活大爆炸版石头剪刀布
开一个表,然后模拟一下就行,很简单的。没坑?
联合权值
由于所有路径的长度都是1,并且枚举的是距离为2的点,我们可以枚举中间点,然后枚举两端的点,这样还是T,我们可以维护前缀和来求所有乘积,每搜索到一条边,乘上了前面的前缀和之后把这个点的前缀和加进去。因为是有序的数对,最后ans*=2。至于最大值,维护一下前缀最大值然后用当前点乘以前缀最大值更新就行了。
像这种前缀优化、乘法原理的思想经常用到,不能说是固定的算法吧,可以说是一个优化的技巧就能AC了。
飞扬的小鸟
像这种dp思想的题,一些大佬的题解经常会说无后效性和最优化,都是啥意思呢,无后效性就是当前你的转移和之前的无关,就是不管你怎么走到这里,你在这里干的事儿都一样。最优化就是要求一个最优化的原则。
这个怎么dp呢,令f[i][j]
表示当前的坐标为(i,j)走到这里的最大值。一开始f[0][j]=0
。然后从左到右遍历整个地图,然后从下到上更新点击,用完全背包的思想,因为你可以点击无限次(但是不能不点)。然后从下到上更新不点击,因为不点击会下降,所以从下到上更新,这是一个0-1背包。然后把所有柱子设成inf。最后更新答案的时候看看最后一列的最小值,如果没有最小值就从右往左扫描地图,找第一个不是inf的位置,往前扫描柱子的个数。
无线网络发射器选址
注意到如果枚举地图会TLE,而点数很少,所以枚举点。
寻找道路
从终点逆着dfs整个图,找出所有能够与终点联通的点,枚举不能与终点联通的点,把指向他的所有点标记为false。然后因为所有边长度为1,从起点在所有合法的点上跑bfs就行了。
解方程
因为n比较小,m也不太大,所以枚举所有[1,m]内的数,利用秦九韶算法在O(n)算出表达式的值,因为ai很大,而我们不想使用高精度,所以我们可以模一个质数。不知道为什么模合数会出锅。。。模雷哥,模NTT,模江主席都可以
NOIP2013
转圈游戏
推理很重要。如下
0号走1轮到m号,那么0号走B轮到(m*B)%n
0号走10^k轮到(m*10^k)%n
,优化后(m%n*(10^k)%n)%n
所以x号走10^k轮优化后得到((m%n*(10^k)%n)%n+x)%n