ACM学习经验.docx
- 文档编号:7458228
- 上传时间:2023-01-24
- 格式:DOCX
- 页数:24
- 大小:43.02KB
ACM学习经验.docx
《ACM学习经验.docx》由会员分享,可在线阅读,更多相关《ACM学习经验.docx(24页珍藏版)》请在冰豆网上搜索。
ACM学习经验
入门篇
1、acm入门经验
对于还没有方向处于盲目阶段的acmer新手会有所帮助。
1、先大概浏览《算法导论》,。
2.注册OJ账号,找AC人数最多的做,或者找自己会做的做,不会的一概不管。
遇到不会做的题目,尽量自己想,想不出找同学讨论discuss,也可以搜索解决报告。
3、多做题,一定要多做题,每天至少(是至少)过个几题(1题也行,但一定要做,天天做,有空就做)
4、有空多看看别人的代码,不管这题你是过了还是没过,最好都仔细读读,吸取其中写的好的地方,尤其是新手,多看看别人的代码很有好处。
5、有问题不懂可以在acm群、acm百科网问问题,因为主要是自学,交流很重要,在(且只有在)想不出来看不懂书网上又搜不到自己实在无法解决时,一定要多问,死缠烂打地问。
6、有一定水平后,各个OJ,topcoder,所有的比赛都要关注,能做的比赛尽量做,不管刚开始你有多菜,一题都做不出来也要去参加。
并在赛后总结,尽量把能做的题目干掉。
7、所有的大牛都是从只会简单题开始的,不管你现在多菜,只要你坚持,总有一天你会变成大牛。
8、原来以为只有ACM会辛苦,后来和别人交流了,其实所有的专业比赛(计算机方面)都很辛苦,不仅辛苦,而且都需要很长时间,没有任何比赛是你说随便搞搞短时间就能出成绩的,拼的都是内功,成功没有捷径。
如果选择ACM,就一定要坚持,而且必须放弃很多其他东西,不要什么都做什么都没成绩,有所得必有所失。
2、对ACM新人的建议
一、语言是最重要的基本功
无论侧重于什么方面,只要是通过计算机程序去最终实现的竞赛,语言都是大家要过的第一道关。
亚洲赛区的比赛支持的语言包括C/C++与JAVA。
首先说说JAVA,众所周知,作为面向对象的王牌语言,JAVA在大型工程的组织与安全性方面有着自己独特的优势,但是对于信息学比赛的具体场合,JAVA则显得不那么合适,它对于输入输出流的操作相比于C++要繁杂很多,更为重要的是JAVA程序的运行速度要比C++慢10倍以上,而竞赛中对于JAVA程序的运行时限却往往得不到同等比例的放宽,这无疑对算法设计提出了更高的要求,是相当不利的。
其实,并不主张大家在这种场合过多地运用面向对象的程序设计思维,因为对于小程序来说这不旦需要花费更多的时间去编写代码,也会降低程序的执行效率。
接着说C和C++。
许多现在参加讲座的同学还在上大一,C的基础知识刚刚学完,还没有接触过C++,其实在赛场上使用纯C的选手还是大有人在的,它们主要是看重了纯C在效率上的优势,所以这部分同学如果时间有限,并不需要急着去学习新的语言,只要提高了自己在算法设计上的造诣,纯C一样能发挥巨大的威力。
而C++相对于C,在输入输出流上的封装大大方便了我们的操作,同时降低了出错的可能性,并且能够很好地实现标准流与文件流的切换,方便了调试的工作。
如果有些同学比较在意这点,可以尝试C和C++的混编,毕竟仅仅学习C++的流操作还是不花什么时间的。
C++的另一个支持来源于标准模版库(STL),库中提供的对于基本数据结构的统一接口操作和基本算法的实现可以缩减我们编写代码的长度,这可以节省一些时间。
但是,与此相对的,使用STL要在效率上做出一些牺牲,对于输入规模很大的题目,有时候必须放弃STL,这意味着我们不能存在“有了STL就可以不去管基本算法的实现”的想法;另外,熟练和恰当地使用STL必须经过一定时间的积累,准确地了解各种操作的时间复杂度,切忌对STL中不熟悉的部分滥用,因为这其中蕴涵着许多初学者不易发现的陷阱。
通过以上的分析,我们可以看出仅就信息学竞赛而言,对语言的掌握并不要求十分全面,但是对于经常用到的部分,必须十分熟练,不允许有半点不清楚的地方,下面我举个真实的例子来说明这个道理——即使是一点很细微的语言障碍,都有可能酿成错误:
在清华的赛区上,有一个队在做F题的时候使用了cout和printf的混合输出,由于一个带缓冲一个不带,所以输出一长就混乱了。
只是因为当时judgeteam中负责F题的人眼睛尖,看出答案没错只是顺序不对(答案有一页多,是所有题目中最长的一个输出),又看了看程序发现只是输出问题就给了个Presentationerror(格式错)。
如果审题的人不是这样而是直接给一个WrongAnswer,相信这个队是很难查到自己错在什么地方的。
现在我们转入第二个方面的讨论,基础学科知识的积累。
二、以数学为主的基础知识十分重要
虽然被定性为程序设计竞赛,但是参赛选手所遇到的问题更多的是没有解决问题的思路,而不是有了思路却死活不能实现,这就是平时积累的基础知识不够。
2009年WorldFinal的总冠军是波兰华沙大学,其成员出自于数学系而非计算机系,这就是一个鲜活的例子。
竞赛中对于基础学科的涉及主要集中于数学,此外对于物理、电路等等也可能有一定应用,但是不多。
因此,大一的同学也不必为自己还没学数据结构而感到不知从何入手提高,把数学捡起来吧!
下面我来谈谈在竞赛中应用的数学的主要分支。
1、离散数学——作为计算机学科的基础,离散数学是竞赛中涉及最多的数学分支,其重中之重又在于图论和组合数学,尤其是图论。
图论之所以运用最多是因为它的变化最多,而且可以轻易地结合基本数据结构和许多算法的基本思想,较多用到的知识包括连通性判断、DFS和BFS,关节点和关键路径、欧拉回路、最小生成树、最短路径、二部图匹配和网络流等等。
虽然这部分的比重很大,但是往往也是竞赛中的难题所在,如果有初学者对于这部分的某些具体内容暂时感到力不从心,也不必着急,可以慢慢积累。
竞赛中设计的组合计数问题大都需要用组合数学来解决,组合数学中的知识相比于图论要简单一些,很多知识对于小学上过奥校的同学来说已经十分熟悉,但是也有一些部分需要先对代数结构中的群论有初步了解才能进行学习。
组合数学在竞赛中很少以难题的形式出现,但是如果积累不够,任何一道这方面的题目却都有可能成为难题。
2、数论——以素数判断和同余为模型构造出来的题目往往需要较多的数论知识来解决,这部分在竞赛中的比重并不大,但只要来上一道,也足以使知识不足的人冥思苦想上一阵时间。
素数判断和同余最常见的是在以密码学为背景的题目中出现,在运用密码学常识确定大概的过程之后,核心算法往往要涉及数论的内容。
3、计算几何——计算几何相比于其它部分来说是比较独立的,就是说它和其它的知识点很少有过多的结合,较常用到的部分包括——线段相交的判断、多边形面积的计算、内点外点的判断、凸包等等。
计算几何的题目难度不会很大,但也永远不会成为最弱的题。
4、线性代数——对线性代数的应用都是围绕矩阵展开的,一些表面上是模拟的题目往往可以借助于矩阵来找到更好的算法。
5、概率论——竞赛是以黑箱来判卷的,这就是说你几乎不能动使用概率算法的念头,但这也并不是说概率就没有用。
关于这一点,只有通过一定的练习才能体会。
6、初等数学与解析几何——这主要就是中学的知识了,用的不多,但是至少比高等数学多,我觉得熟悉一下数学手册上的相关内容,至少要知道在哪儿能查到,还是必要的。
7、高等数学——纯粹运用高等数学来解决的题目我接触的只有一道,但是一些题目的叙述背景往往需要和这部分有一定联系,掌握得牢固一些总归没有坏处。
以上就是竞赛所涉及的数学领域,可以说范围是相当广的。
我认识的许多人去搞信息学的竞赛就是为了逼着自己多学一点数学,因为数学是一切一切的基础。
三、数据结构与算法是真正的核心
虽然数学十分十分重要,但是如果让三个只会数学的人参加比赛,我相信多数情况下会比三个只会数据结构与算法的人得到更为悲惨的结局。
先说说数据结构。
掌握队列、堆栈和图的基本表达与操作是必需的,至于树,我个人觉得需要建树的问题有但是并不多。
(但是树往往是很重要的分析工具)除此之外,排序和查找并不需要对所有方式都能很熟练的掌握,但你必须保证自己对于各种情况都有一个在时间复杂度上满足最低要求的解决方案。
说到时间复杂度,就又该说说哈希表了,竞赛时对时间的限制远远多于对空间的限制,这要求大家尽快掌握“以空间换时间”的原则策略,能用哈希表来存储的数据一定不要到时候再去查找,如果实在不能建哈希表,再看看能否建二叉查找树等等——这都是争取时间的策略,掌握这些技巧需要大家对数据结构尤其是算法复杂度有比较全面的理性和感性认识。
接着说说算法。
算法中最基本和常用的是搜索,主要是回溯和分支限界法的使用。
这里要说的是,有些初学者在学习这些搜索基本算法是不太注意剪枝,这是十分不可取的,因为所有搜索的题目给你的测试用例都不会有很大的规模,你往往察觉不出程序运行的时间问题,但是真正的测试数据一定能过滤出那些没有剪枝的算法。
实际上参赛选手基本上都会使用常用的搜索算法,题目的区分度往往就是建立在诸如剪枝之类的优化上了。
常用算法中的另一类是以“相似或相同子问题”为核心的,包括递推、递归、贪心法和动态规划。
这其中比较难于掌握的就是动态规划,如何抽象出重复的子问题是很多题目的难点所在,笔者建议初学者仔细理解图论中一些以动态规划为基本思想所建立起来的基本算法(比如Floyd-Warshall算法),并且多阅读一些定理的证明,这虽然不能有什么直接的帮助,但是长期坚持就会对思维很有帮助。
四、团队配合
通过以上的介绍大家也可以看出,信息学竞赛对于知识面覆盖的非常广,想凭一己之力全部消化这些东西实在是相当困难的,这就要求我们尽可能地发挥团队协作的精神。
同组成员之间的熟练配合和默契的形成需要时间,具体的情况因成员的组成不同而不同,这里我就不再多说了。
五、练习、练习、再练习
知识的积累固然重要,但是信息学终究不是看出来的,而是练出来的,这是多少前人最深的一点体会,只有通过具体题目的分析和实践,才能真正掌握数学的使用和算法的应用,并在不断的练习中增加编程经验和技巧,提高对时间复杂度的感性认识,优化时间的分配,加强团队的配合。
总之,在这里光有纸上谈兵是绝对不行的,必须要通过实战来锻炼自己。
大家一定要问,我们去哪里找题做,又如何检验程序是否正确呢?
这大可不必担心,现在已经有了很多网上做题的站点,这些站点提供了大量的题库并支持在线判卷,你只需要把程序源码提交上去,马上就可以知道自己的程序是否正确,运行所使用的时间以及消耗的内存等等状况。
下面我给大家推荐几个站点,笔者不建议大家在所有这些站点上做题,选择一个就可以了,因为每个站点的题都有一定的难易比例,系统地做一套题库可以使你对各种难度、各种类型的题都有所认识。
1、Ural:
Ural是中国学生对俄罗斯的Ural州立大学的简称,那里设立了一个UralOnlineProblemSet,并且支持OnlineJudge。
Ural的不少题目算法性和趣闻性都很强,得到了国内广大学生的厚爱。
根据“信息学初学者之家”网站的统计,Ural的题目类型大概呈如下的分布:
题型搜索动态规划贪心构造图论计算几何纯数学问题数据结构其它
所占比例约10%约15%约5%约5%约10%约5%约20%约5%约25%
这和实际比赛中的题型分布也是大体相当的。
有兴趣的朋友可以去看看。
2、UVA:
UVA代表西班牙Valladolid大学(UniversitydeValladolid)。
该大学有一个那里设立了一个PROBLEMSETARCHIVEwithONLINEJUDGE,并且支持ONLINEJUDGE,形式和Ural大学的题库类似。
不过和Ural不同的是,UVA题目多的多,而且比较杂,而且有些题目的测试数据比较刁钻。
这使得刚到那里做题的朋友往往感觉到无所适从,要么难以找到合适的题目,要么WrongAnswer了很多次以后仍然不知道错在那里。
如果说做Ural题目主要是为了训练算法,那么UVA题目可以训练全方位的基本功和一些必要的编程素质。
UVA和许多世界知名大学联合办有同步网上比赛,因此那里强人无数,不过你先要使自己具有听懂他们在说什么的素质:
)
3、ZOJ:
ZOJ是浙江大学建立的ONLINEJUDGE,是中国大学建立的第一个同类站点,也是最好和人气最高的一个,笔者和许多班里的同学就是在这里练习。
ZOJ虽然也定位为一个英文网站,但是这里的中国学生比较多,因此让人觉得很亲切。
这里目前有500多道题目,难易分配适中,且涵盖了各大洲的题目类型并配有索引,除此之外,ZOJ的JUDGE系统是几个网站中表现得比较好的一个,很少出现WrongAnswer和Presentationerror混淆的情况。
这里每月也办有一次网上比赛,只要是注册的用户都可以参加。
3、学习心得
1、语言是最重要的基本功。
2、以数学为主的基础知识最重要。
3、团队合作很重要。
4、练习,练习,再练习。
努力,努力,再努力!
不变的学习方法。
集训篇
1、指导思想
(1)长期积累
弱校生源:
无OI基础、无编程基础、第一志愿不满
时间:
最少2年以上,乃至大学4年
题数:
500题入门、1000题参加省赛
银牌:
1000题以上、3人
破除学生做一个月题就来比赛的思想。
(2)方针
①兴趣主导
玩编程、玩ACM、玩脑子
相反:
越做越痛苦
②重视能力培养
多看书、看论文,少看解题报告
多问、多学思路,少看代码
一题多解、精益求精、少做水题、尽量啃难题
③能力要求
编程能力:
100行左右的代码不用调试,最好150行
思维能力:
100行左右的代码想清楚再写,而不是边写边想
算法和建模能力
破除学生看本数据结构或算法书就想比赛的思想
2、训练组织
(1)宣传和动员
①动员越早越好、从大一入学开始
宣讲会
程序设计课程
大一积累题数:
练习编码能力和思维能力
大二学习算法,大三出成绩
②参加学生越多越好,走大众路线
组织ACM协会、常设集训队
组织培训、周赛、月赛
以老带新
(2)人员选拔
①能力突出型
学习拔尖、各方面能力优秀、非常爱好编程序
最适合ACM竞赛,想办法吸引过来
不是每个学习成绩拔尖的学生都是能力突出的,这种学生非常少,仔细发掘
队伍中的主角
②沉迷型
适合ACM竞赛、提高快、越做越顺
但这种学生一旦被其他事情吸引,就很难回头
缺点:
考试成绩、碰到做题困难
队伍中的主角
③乖宝宝型
成绩优秀、平时深受老师喜爱
能力不强、碰到困难易退缩
多鼓励
队伍中的配角
④以证书为目的
碰到困难犹豫不决
退出率高、1/2的能保留到第二年
带着他们一起学
队伍中的配角
⑤自信心不足型
提早开始,重在坚持
入门时善于引导
3、训练内容
(1)基本方针
先做题、后看书
先练脑子、后学知识
(2)步骤
三个阶段:
从大一到大三
(3)第一阶段:
从大一寒假开始,至省赛、区域赛,半年多时间
内容:
刘汝佳的《算法竞赛入门经典》和《挑战编程》
涵盖:
数据结构、搜索、暴力、分治、贪心、动规、数论、递推、图的最短路和最小生成树、网络流
水题多、有讲解、入门快、积累题量
403题
将坚持下来的重点培养,做完第一阶段的视作入门了
(4)第二阶段:
大二学年,非常重要的一年
内容一:
USACOTrainning,98题
非常经典、有难度、练编码能力和思维能力
内容二:
POJ分类训练,超过280题
内容全面,补充第一阶段缺少的知识,有部分难题
学生学会自己找训练内容
内容三:
开始看书、看论文
算法导论、算法艺术与信息学奥赛、组合数学
国家集训队论文、网上资料
内容四:
SGU,超过500题
http:
//acm.sgu.ru/
题目难度大,锻炼思维能力
(5)第三阶段(实际经验):
大三学年,至大四参加区域赛出成绩
继续第二阶段未完成的部分
参加各种网络比赛(TopCoder和Codeforces)
深入研究1~2个分类的知识和题目
拿手的
数论和代数方程
概率、组合、博弈
动态规划
字符串
数据结构(链表和树的应用)
图论
暴力和搜索剪枝
计算几何
4、比赛准备
(1)时间分配
多做题目,学习知识
暑假训练以模拟比赛为主
利用HDOJ和VirtualJudge
挑选队员,调整组队,练习配合默契
笨鸟先飞,重在坚持
(2)组队
一支队伍中一定要有一个比较冷静的同学,即使能力稍弱
现场比赛经验非常重要,多打比赛
(3)网络赛
网络赛的难度要高于现场赛
没有一支银牌实力的队伍(3个人以上),很难稳保从网络赛出线
网络赛没有出线的学校是可以优先申请现场赛名额的
规则:
鼓励学生认真打网络赛
走捷径其实不利于学生的成长,也不利于ACM竞赛的展开
因为ACM竞赛对能力的要求很高,除了苦练没什么太好的办法,所以队内风气很重要
5、看法
(1)公司对ACM竞赛的看法
XX、RedHat、淘宝、搜狐、小米等公司对省赛、区域赛奖牌获得广泛认可
对研究生笔试或机试题会有很大帮助
(2)本人对ACM竞赛的看法
给自己一个接触外界的机会
给自己一个自我认识的机会
调试篇
1、ACM中WA方面的错误总结
1、Int遇到过的问题
简介:
int是最常用的类型之一。
如果输入数据是整形,一般都直接用该类型来存放输入数据。
错误经历:
在作EquiptmentBox时,因为输入数据长、宽均是小于50000的整数,因此就使用int来作输入。
这本身没有问题,但在求其斜边长时,使用的是sqrt(x*x+y*y),表面看是没有问题,但结果一直是WrongAnswer。
后来将这一行改为pow((pow(x,2)+pow(y,3)),0.5),就Accept了!
错误原因:
后来经johnbill和hewei的分析,x,y本身没有问题,不会越界,但使用sqrt(x*x+y*y)时,里面的x*x和y*y则会超出int范围,造成溢出。
而pow会将参数自动转换为double,就不会出错。
避免失误的办法:
(1)以后均使用pow进行运算。
(习惯)
(2)运算时,注意做强行转换。
(比较麻烦)
(3)不管输入给的类型,直接用double来存储,就不会溢出了。
这种方法表面看没有问题,但直到这次比赛,才发现了一个很严重的问题!
2、double遇到过的问题
简介:
在解题时,和int一起是最常用的类型。
错误经历:
因为double上限可达1.7e308。
而一般题目(非大数运算要求)均不可能超过其限,发生溢出,所以之后我就在做题时,凡是遇到结果有些大时,均用double类型来保存,来避免溢出。
看起来,这样比较方便,因为在本机上是用VC++,而OnlineJudge是gcc,它们支持的长整形类型不同,一个是__int64,而一个是longlong;处理格式也不同,I64u和lld。
而在这种情况下,“真正”的可以用double的话,那就可以将其统一起来。
在比赛C题时,也是这么递推和用double保存,但一直WrongAnswer。
和递归能计算出(太大的数据很耗时)的数据相比,都是正确的,不知原因何在。
比赛结束后,和别人结果对照了一下,把double改成unsignedlonglong就Accept了。
错译原因:
这是因为:
double类型的精度只有15位!
!
!
它的上限可以很大,但只能保证15位的精度!
换句话说,只能保证15位是正确的。
在数据(50,50)以后,结果都在20位以上,前面的位数是正确的,但后面的几位就会出现问题了!
解决方法:
(1)定义头文件,在本机上用__int64,提交时用longlong
(2)本机上使用VAC编译(J)(奇难用!
)
(3)反正绝对不能使用double来计数,尤其比较大的数,但可以利用它来测试最大数据的范围大小,这样可以反过来帮助我们决定用什么类型来保存。
3、float遇到过的问题
记得当时Hunter做area的时候,各方面都作了考虑,但一直是WrongAnswer。
后来只是把存储坐标的float类型改为double,就过了。
原因:
应该是float的精度不够(具体嘛…..大家re),但题目只要求3位小数也有问题……。
所以,以后大家要使用浮点数计算时,直接用double,不要考虑使用float。
一般内存是不会有问题的。
4、4舍5入的问题:
在做LiftingtheStone时,题上要求保留到小数点两位,第三位作四舍五入,自己直接用%.02来打,以为自动会四舍五入。
但一直没过。
加上处理之后就过了…….
原因:
小数点后第三位为5时,会随机的作进位处理。
解决办法:
如果题上要求了四舍五入,一定要记得进行处理:
x=floor(x*100+0.5)/100,
5、为5时,后一位奇数进位,偶数不进位。
解决办法:
除了相当的灵活,多试,还需要运气。
2、调试和测试总结
1.下面是几种比较常见的错误:
①输入输出格式错误
②数据类型错误(尽量用大的类型)
③范围检查错误(可以稍稍加大上下界)
④变量名称错误
⑤漏语句(看事先设计好的变量是否都用上了,然后看每个模块是否实现了应有的功能,是否完成了接口)
2.我们应对于每道题设计充分的测试数据,并保留那些比较具有代表性的测试数据,以便于优化的时候比对.
3.一定要记住删除屏幕输出!
4.最后一定要记住关闭程序中用于临时调试的特殊设置和语句!
5.输出数据的每一行(包括最后一行)必须以一个换行符结束,行末不要保留多余空格。
对于每一道试题,在相应的目录中都有一个格式检查程序来检查输出文件格式的合法性。
该程序的文件名是:
格式检查程序仅仅检查输出文件名的正确性和文件格式的合法性而不检查结果的正确性。
检查结果显示在屏幕上。
6.如果领队或参赛选手对评测结果有异议,可以填写相应的表格,并在评测结果公布后的三个小时之内提交评测委员会申请复议或复评。
当领队或参赛选手对复议或复评结果仍有异议时,应提交NOI科学委员会仲裁,并以NOI科学委员会的仲裁结果为该项评测的最终结果。
7.调试的时候,一定要钻输入文件的牛角尖,考虑到各种情况。
8.调试的时候,常常可以编一个非常非常易编的程序,采用算两次的方法,不过前提是必须保证正确。
9.Writeln是Fp中最笨但又是最准确的调试方法。
10.调试时每发现一个错误,都最好浏览一下整个程序,看是否有类似错误,这样非常有效!
11.在每一处可以中止程序的地方,都要看一看是否需要closefile.
12.程序出现不确定性的问题,如对于同样数据,有时死机,有时不死机,但多半都是随机模块有误!
13.指针出错常常是出现了Nil^.Next
14.递归程序的调试应该使用F7(F8)+CallStack,尽量不要用F4。
15.不要只顾埋头拉车,要抬头看路。
当被一两个子程莫名其妙的错误弄得晕头转向的时候,记住:
很可能错误在其他地方。
16.读写文件之前才打开文件,操作完毕立即关闭。
17.每改完一个错误要想想是否改正确了,是否改彻底了,程序中(特别是有Paste的地方)是否有相同错误。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACM 学习 经验