Noip2013错误避免
很多的时候,我们会说,这道题我会做,算法想出来了,但是这里那里少了一些判断,导致一分未得,或是说变量名错误,或者说干脆是文件名错误。这些都不是理由,如果火箭发射半空爆炸,可以说是控制器中一个运算符错误就可以逃避所有责任吗?不可以,同样,OI也不行,所以只有提升自己,使自己成为一个严谨的人!
基本操作
1.读题一定要仔细,特别是长题目,千万不要主观臆断,一定要完全理解题目再去编程。A good reader is what he reads! 读题时要注意用样例模拟一下自己所理解的题目意思,若正确才开始编程。
2.文件读入与输出检查很重要,最好指定路径在自己电脑上试一下,不过不要忘记将路径改回来。如果比赛时电脑没问题时,直接在原文件夹下进行。
3.特别注意数组范围一定要开的大一些,而且下界最好定为-1。特别是一些会调用0和-1 的题目。
4.看清题目输出,比如‘good!’,千万不要少打一个‘!’导致全盘皆输。
5.变量一定不要打错,上次在打小根堆时最后交换变量打错,将t赋值为父亲,父亲赋值为儿子之后,又把儿子赋值成了父亲,结果本来AC的程序变成了全错。
初始化
1.给数组赋初值时,如果一会要相加判断的,一定记住赋保险一点的 ($7f div 3),如果有相乘判断的也必须注意相乘超上限的问题(215错误)。
2.在计算时初始化很重要,特别记住LIS数组和答案的初始化都为1。因为本身就是一个lis。
3.关于fillchar与filldword:
fillchar是赋值极大值,0和-1时用的,int64与longint均可:
fillchar(a,sizeof(a),$7f):赋值为极大值;
fillchar(a,sizeof(a),0):赋值为0;
fillchar(a,sizeof(a),$FF):赋值为-1;
filldword是赋值任意值用的,但是只限longint:
filldword(a,sizeof(a)>>2,x):赋值为x;
注意右移2位,因为是按位赋值的所以一定要右移。
还有如果是小范围赋值,不是整个数组的话,用for循环更快!
4. 并查集在运算前一定要预处理 f[i]=I, 否则后果很严重。
范围选择
1. 一定要看清数据范围,并且计算出中间变量的隐藏范围,才决定用int64或是longint,在能使用longint的情况下不要使用int64,因为会降低速度。
2.堆式线段树范围一定要开至六倍左右,最为保险,位运算压缩内存如果记不清就不要用了。
3.前向星数组要开到边数的两倍以上,否则会内存溢出。
算法错误
1.切记,前缀和一定要在排序后计算,否则会导致出错。
2.最短路弗洛伊德算法循环一定不可以换!Dijkstra算法不能求有负权的最短路!
3.特别记住,pos函数字串写在母串前,返回值为字串在母串中位置。
4.在打二分答案的代码时,一定要注意,分清楚答案是单调递增或是单调递减,调试不出时可以考虑一下这个致命错误,比如我在做聪明的质检员时,没分析清楚答案单调性的走向,导致错误,太可怕了。
5.在打链表插入时,一定要注意是x<a[i].brother 且((x<I)or(a[i].brother=0)))时插入。(特别注意,是x<a[i].brother 而不是x<i),调试时特别注意~
6. 记住,在利用循环变量求一个值时一定要用范围扩大法,而且切记不能打成k:=int64(i*i)而是k:=int64(i)*int64(i)。
7. 树状数组和线段树边界条件一定要看清楚,等于有还是没有一定认真思考,多次被坑的经验。
8.并查集中并入的操作为f[f[i]]=f[j],不要少打f。
9.如果在过程中要改变过程里的变量,则要用var比如扩欧。
程序优化
1.同一个数据不要反复计算,可以保存以提高程序效率,比如打聪明的质检员时,我本来打的是check与s比较,将check与s做差,与tmp比较,反复调用了两次过程,就在nlogn的算法中加入了2的常数,后果可想而知,时间扩大了两倍啊!
2.在判断两个条件用and连接时,应该让适用范围狭窄的放在前面,这样就可以减少判断次数,因为如果第一个条件不满足就不会去判断第二个条件,切记,有些时候,这是一个很强大的优化。
3.位运算相当重要,比如二分或是简单的乘除,若可以用上则尽量代替。
4.集合的搬运用Move函数取代直接复制:
Move(f[I],g[j],s*sizeof(f[1]));
表示从f数组第I为开始搬运s长度的数据至g数组第j位开始的地方。
内存占用计算
千万不要因为超内存而0分!
1 字节 :Boolean -- 布尔型 ; int Short ( -128~127 ) , Byte ( 0~255 ) -- 最小的整型 ; char --字符型 ;
2字节: Integer ( -32768~32767 ) 、 Word ( 0~65535 ) -- 常用的整型 ;
4字节: longint ( -2147483648~2147483647 ) -- 长整型; Single ( 1.5e-45~3.4e38 )-- 单精实型 ;
6 字节: real( 2.9e-39~1.7e38 ) -- 标准实型 ;
8字节: Int64 ( -2^63+1~2^63-1 ) -- 整型; Double ( 5.0e-324~1.7e328 ) -- 双精度实型; Qword ( 0~2^64-1 ) -- 整型; Comp ( -2^63+1~2^63-1 ) -- 装配十进制实型 ;
10字节:Extended ( 1.9e-4951~1.1e4932 ) -- 扩展实型 ;
特殊:String (长度最大为 255 的字符串 ) ; Ansistring (超长字符串 , 长度不限) .
算空间的公式:总空间 =( 总字节数 /1024/1024)MB
比赛限制: NOIP:256MB; ZJOI:512MB
题目细节
有时候考完模拟赛,总会有这样的抱怨声:希哥的数据怎么这么坑啊,怎么想的到。NOIP肯定也是会有这样的数据的,许多的时候,不是我们想不到,而是没有去想,只是过了样例就欣喜若狂,或是仅仅是样例一类的小数据。在做题完后,一定要从一个出题者的难度划分角度思考,那些地方可以坑人,就比如smartoj里数星星这一题,没说给出的坐标X2>X1且Y2>Y1,所以就要分类讨论,还有就是0的考虑,高精度负数特殊处理的考虑,组合数1和0的考虑,递归边界的考虑,不要给数据一点可趁之机。
数据制造
如何在一个过了样例的程序里检查呢,只有自己制造测试数据,测试数据分为几种:
- 小数据,可以手动验证准确性的数据。
- 中等数据,对拍时使用(不过要保证暴力程序的正确性)
- 边界数据,选取一些容易出现问题的数据,看看程序是否会崩溃。
- 极限数据,写一个程序maker制作数据,看是否发生栈溢出或是其他一些错误。用时间函数记录时间观察是否超时。
时间函数:
Uses sysutils; time:real;
Begin
Time:=now;
…… { 主程序部分 }
Writeln((now-time)*86400:0:3);// 时间变量的单位是 “ 天 ” , 所以要转化为 “ 秒 ”
End.
P处理样本:
:loop
maker.exe>cut.in
cut.exe<cut.in>cut.out
cut1.exe<cut.in>cut1.out
fc cut.out cut1.out
if errorlevel 1 goto end
pause
goto loop
:end
Pause
——2013年11月6日
愿你出走半生,归来仍是少年