欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【自用】杂乱无章的整理。。。

程序员文章站 2022-05-07 23:09:28
...

博客草稿箱里有好多要填的坑 考前注意看看

这两天被规律题虐得不行
因为我都是那种,通过题意看性质的做法。。
然鹅性质可能过于复杂,看不出来
所以就要打表。。。
####手打+程序打结合,手打验证正确性,程序打表是为了打的更大一点,因为很多时候手打表打的小了观察不出规律
就是,真的去把表格列出来,找上下行,不同列的关系
还有就是找规律真有可能找错,
##先打好暴力,然后对拍什么的网盘里有对拍程序
还有 写代码的时候一定要动脑子!动脑子!动脑子! 特别是那种
x x x x x x x
x x x x x x x
x x x x x x x
x x x x x x x
这样的
比如说有x次操作,每次操作是ai=ai+aimodn+1a_i = a_i + a_{i mod n + 1}求第x次操作后位置y的数是多少
打出表来。。。
1 2 3 4 5
3 5 7 9 6
8 12 16 15 9
20 28 31 24 17
然后发现每个数都是他上面两个数的和
然后看看位置y的数是怎么加起来的,会发现这个东西和组合数用关系


###关于智商题…
这两天被智商题虐的不行。。。
其实我的思维方式有问题…我总是不去模拟那个过程,而是非常“混沌”地想这是什么,但是混沌的想法怎么能出来清晰的解法呢…就得按部就班地进行那个过程,看看这个过程会发生什么,特别注意若有n个东西移动,那么把范围小一点,只考虑一两个,然后推出来某结论时也要注意不能丢了题意给的过程,所以说逻辑是战胜混沌的重要方法啊…
比如说洛谷上的独木桥那题
如果我画画图,模拟人怎么走,走完后又是什么状态,结合每个人速度一样就能找到解法
但是我最不好的地方就是找到了一个性质后,非要热衷于找反例
找反例是好的,但是很多时候乱构造出的反例可能不存在,但是有时候又容易忽视掉不存在那种情况的可能
导致题做不出来
而且我总是“混沌”地想,数据这么乱,怎么可能都满足这个性质呢
但是这是题啊。。。题一定有他的做法的,你总要依据题意,从中挖掘出什么重要性质,而且oi不需要证明
关键是找反例这里,千万不要构*例了,以自己的角度很难知道这个反例哪里不合理,只要证明那个性质具有普遍性就可以了
所以说性质别乱找反例,但贪心可以找反例,因为容易贪错


####“!” 运算符的优先级很低,所以注意判断奇偶数时要在括号里%
!(a%2) 或者直接if(a%2)判断是奇数吧
###同时也要注意,即使考场上没有部分分的数据,写完部分分后自己造一组那样的数据测一下,防止出现低级错误

注意 双向边定义数组大小时必须写乘2
这个有时候忘了就很难受,就写e[MAXN*2],反正一定要记着数组开两倍(因为大多数时候N,M同级,所以就写MAXN了)
###多组数据数组记得清0,多次操作记得清0,比如建新图,基本都要清,包括邻接表总数totnew,再比如说dfs的vis数组,还有每次vis[1] = 1, ans = 0 清空上一次,最小值初始为1<<30最大值设为0,这个别忽略,有一题多组询问,要求我选任一个点,每次跑最短的,然后我写了n^3暴力做法,但是每次询问前我都需要把答案设为1<<30 因为我每次询问就要出一个答案,而上一次的询问和这一次的没有关系,看来一个询问的答案最好开在循环里 实在要开全局的一定注意每次更新(不同的询问)时答案必须先设为0或1<<30 具体看寻宝游戏写的暴力

总之就是多写memset

模的时候要注意 举个例子 比如说我要绕环走,那么我的位置就是(y+k)% n y起始位置(把y+n当做一个整体,从1号点走到y再走到n),k走的距离,n个数
那么有个问题 如果说y+k == n的倍数 那么%后变为0,但是我们应该走到n的
可以设a[0] = a[n]
也可以只考虑k,把k单独%n 再加上y 特判当y+k%n > n 时减去n
也就是说%n次之后正好回到了y,再考虑剩下怎么走
然而还是容易错,出几组极特殊的例子测测就行
或者更简单的办法是从0开始计数 当y+k = n时模一下正好回到开头 而n-1是结尾0是开头

字符串从0到n-1
状压dp从0到 (1<<n)-1

如果说一个题,调了半天,然后勉强过了样例,把一个算法修修补补,那很有可能写错了,最好重新做下这道题 必须要重看一遍题面,把整个过程把握住,不要想到哪写到哪,写的程序要有条理。。。我17年时间复杂度本来该拿100分,但是拿了70,因为我调过了大样例,但估计只是勉强过得,我并没有想用两个栈,我只是一边读题一边写

###最好模块式编程,先写函数名和注释,说明函数是干什么的,然后先别写函数 把主框架写出来

文件一定不要写错,有时候眼看不出来,抄下来一个个对,或者分时间段多看几次

数组开大点,如果说只用01两个变量开到3 lca倍增20次就行开到25

###注意写%lld !!!

队列开两倍大,万一越界了呢
而且做单调队列题的时候注意若有两个以上的单调队列最好开两个队列数组并且每次都把l,r设为 l = 1 r = 0

数组开大点 比如说开了个dp数组 里面有用0/1表示什么什么 那么得开成dp[3][MAXN]

又被多组询问坑了。。。
多组询问时 若成功则flg = true;
注意这个flg要写成局部变量并且每次都赋false

一定要明确是否有向无向图啊啊啊啊啊啊
读题要认真!
FJ在第i号隔间上张贴了一个“下一个隔间”Next_i(1<=Next_i<=N),告诉奶牛要去的下一个隔间;
这指的是有向边
而有些图需要建无向边,比如奶酪那题,注意题意。

博弈找规律一般都和二进制有关,什么异或啊,或者把每一个状态的二进制转换成十进制之后能发现这个十进制数有什么联系什么的

#开long long 一定记着要开long long 答案 数据超了int一定要有意识地开long long

真实的故事 我是如何wa的

	int maxx = 0;
	for(int i=l; i<=r; i++) {
		maxx = max(maxx, a[i]);
	}

然而一不小心写成了

	int maxx;
	for(int i=l; i<=r; i++) {
		maxx = max(maxx, a[i]);
	}

wa

还有更可怕的。。。

void calc(int p) {
...
}
long long p;
calc(p)

哇 我把longlong填到int参数里了!!!
应该是

void calc(long long p) {
...
}
long long p;
calc(p)

还有 返回值应该是long long 的函数 一不小心定义成返回int的函数了。。。

long long dfs() {
}
printf("%lld", dfs());

int dfs() {
}
printf("%d", dfs());

如何写搜索,搜索和DP内核是一样的 需要记录状态,而不同的分支就是不同的决策
先确定阶段 比如 T40984 Chino的成绩 这题的搜索
阶段是到了第几天,决策是这一天怎么做,我可以继续前几天的方式 或者用另一种方式
##静态查错真的很重要

long long double 的位运算可能会出锅 所以注意这两种类型就老老实实用/2和%2代替位运算吧

注意运用洛谷“推荐的相关题目”进行网形做题

先看数据范围,猜复杂度,然后猜算法

##变量名不要起的长得太像 真的很容易看混乱

一定要长个心眼,别被出题人坑了。。。比如说有个bfs找联通块,要求从第一行开始从左往右然后第二行从左往右,求每个联通块在这种起点下扩展的最大深度 这个最大深度要放在每个元素出队的时候更新,而不是元素入队时候更新,因为可能联通块大小为1,不发生任何入队,而因为最大深度每次重置为0 导致不能更新大小为1的联通块

#对于字符串DP 一般都会给出字符串长度,此时要用字符数组存串,并且写cin >> a+1;这种形式 若不给出字符串长度 用 strlen(a+1)求长度。 为什么不用scanf呢。。因为scanf会读换行符。。。而且字符串DP一般来说复杂度都较大,而输入一般都是几千的数据,所以不在乎cin还是scanf了。。

不仅仅是如此 任何从下标0开始的DP都有可能访问负下标,所以想办法让下标从1开始,而且从0开始不只有负下标这一种可能出错。。。很多时候你想不到,反正从1开始准没错

啊啊啊啊啊我字符串DP访问到-1了好难受啊

所以静态查错太重要了,不仅要思考高级错误,也要思考低级错误,若能大致地证明正确性,那么不妨检查一波坑人的地方,写完一道题后,花个5分钟找找坑点是很好的!顺便也能放松一下,换换思路。可以想想如果自己是出题人面对这么一份代码该怎么卡掉
在静态查错的过程中切不能急躁,要想清楚自己在干什么,自己的算法什么地方可能会有问题,包括高级(想法上的)和低级错误,比如没清空,longlong,负下标, x%n = 0但是想让x为n这样的

特别是那种“水题”,更有可能出现低级错误,因为有算法的题的处理一般是难想难写,相对来说坑人的点不会很多

建议先花时间只看一遍所有的题 不写代码 把思路写在txt上,因为用语言规范自己的思路会自然地发现错误,而一旦开始写代码了就会头晕脑胀。。。不如先把做法想好,但是要先写好输入。。。

另外 对于打开思路
没事打打草,有用的性质都记录下来,零散的思路也画下来
加强或者放宽题目的条件或约束,得到特殊的模型。思考特殊模型的解法并推广到原问题
是否存在一些隐藏的性质?要从边界或特殊情况考虑,猜测性质。
换个思路?正难则反,统计求贡献?像二分一样求解转判定?和组合数是不是有点关系?一般来说Noip题步骤不会特别多,想不出来可能是方向问题

其实最有用的是
根据范围猜正解复杂度,然后根据复杂度猜算法,这样能提供一个思考的方向,一道题要是n^2那自然就是两两之间处理一下什么的。
或者直接把自己学过的算法都来一遍,这个过程其实很快,不到5分钟吧,看看有什么算法能用的,或者说某个算法的某个思想我能借用(因为题可能就是从某个算法得到了启发才出出来的)

话说 签到题可以直接想正解,想完正解要是不放心再打暴力对拍,因为说实话签到题没必要对数据分开写算法了,而且一些水题的暴力做法可能会影响到想正解的思路(可能暴力做法和正解没啥关系。。。毕竟是签到题不会出的那么猛)

一定要算复杂度,要是达到了1e8级别就要卡常,比如stl改成手打的,scanf读入什么的

不会做题了注意找性质,有时候看似没什么关系的性质恰恰是突破点,具体来说就是手玩一下样例,看看量之间有什么关系
今天一道超简单的暴力没打出来。。。题目是给定一个括号序列,求最长合法匹配子序列
暴力n^2可过,然而我没想出来
事实上只要当成括号匹配用栈做就好了,因为所谓的子序列其实没啥影响
我应该先考虑简单的情况开始,再想复杂的
()
这样的情况显然只需要按平常的匹配方式就好了,然后
( ) )
这样的话最后一个右括号直接舍弃掉就好了,然后一直这么做,不能匹配的直接丢掉

注意别老给自己设麻烦,前几天做一个排列组合题怎么也想不到重复的方案是什么形式,我又犯了由一般到特殊的错误方法论,实际上我自己手玩个小的情况就能很好的看出什么样的形式是重复的(比如说让一些人围成一圈坐着,某些人不能坐一块,求方案数,我可以先玩一下只有3个人的时候的情况,并且看看什么样子是重复的,很容易想到重复的方案就是那些旋转以后等效的方案,但是如果我不玩一下,这个问题就会变的很难思考,不如搞个小样例然后猜想一下。。。)

多组数据记得造含有多组数据的小样例,不然可能会被坑。。。

能打表的数学题一定要打表,对于我来说找规律是最好的做法。。。

好好读题好好读题,别再犯什么考试都犯不好好读题的毛病

DP方程最好写在纸上,事实上许多思考过程都放脑子里很容易乱,用纸记录下是很好的!