这是初级组的得分排名总表:
高级组的得分排名总表:
其实计算机最早是为了解决数学问题的数值计算而研制的,最早的编程语言如FORTRAN也是为了解决一些数学问题。
计算机和数学相互影响。计算机的运算模型离不开数学思想,数学的发展强有力地推动着计算机技术向前发展;同时计算机的高速运算能力也大大地推动了数学的发展。
编程实际上是求解某个问题的过程,这个过程实质上是设计算法到实现算法的过程,没有良好的数学思维很难写出高质量的算法和程序。
一维数组和二维数组是数据结构中最基本的数据存储方式,对于刚入门的程序员来说确实很重要,因此排在第二名和第四名的位置很好理解。
字符串是计算机软件界面最重要的展现形式,尤其是在一些商业应用软件中,随处都可以找到字符串的影子。而对字符串的理解深度和编程处理能力,是检验程序员编程经验最有效的方式,因此字符串也成为各大公司最爱出的面试题,排在CCC第三名当之无愧啊。
第五名是决策判断。
对于数据输入流来说,计算机能够做的最有效的工作就是对于输入数据根据预先设定的条件进行逻辑判断产生分流,从而形成不同的结果和分类,用计算机语言来表达,就是会有大量的IF...ELSE...和SWITCH....CASE...,这种能力和经验对于程序员来说至关重要,决策判断自然就登上了第五名。
第六名是递归编程。
在编程算法领域,递归编程相对前几名而言属于高级课题,一个函数自恋地调用自己无数次,对于初学编程的同学来说有一些难度,递归编程的题目大多在后面的难题部分。
将数据分析的范围限定在后面难题部分,我们发现19道递归编程题都落在第3题以后,10道题落在了最后一道第5题上面。换句话说,CCC把递归编程作为一个高难度出题方向,想要在CCC中获得高分的同学一定需要加强递归编程的练习啊。
下面我们以解数学题、字符串、递归编程为例来说明CCC是怎么玩的吧。
# include <stdio.h>
# include <ctype.h>
FILE * infp;
FILE * outfp;
int t, /* number of test cases */
i,j, /* indexes in array A */
A[50]; /* arrays to store the digits of a number */
char line[61]; /* a character array to store an input line */
void subtract( int i )
/* subtract A[i] from the number represented by A[0..(i-1)] */
{
int j;
if ( A[i]<=A[i-1] ) A[i-1] = A[i-1] - A[i];
else {
A[i-1] = A[i-1] - A[i] + 10;
for ( j=i-2; A[j]==0; j-- ) A[j]=9;
A[j]--;
}
}
main()
{
infp = fopen( "div.in", "r");
outfp = fopen( "div.out", "w");
fscanf(infp, "%d\n", &t);
while (t>0) {
fgets(line, 60, infp); /* get number */
fprintf(outfp,"%s",line); /* print number once */
/* convert from characters to digits */
for (i=0; isdigit(line[i]); i++ ) A[i]=line[i]-'0';
while ((A[0]!=0 && i>2) || (A[0]==0 && i>3)) {
i--;
subtract(i);
if (A[0]!=0) fprintf(outfp,"%d",A[0]); /* don't print leading zero */
for (j=1; j<i; j++) fprintf(outfp,"%d",A[j]);
fprintf(outfp,"\n");
}
line[strlen(line)-1]='\0'; /* remove end-of-line */
fprintf(outfp, "The number %s ", line);
if ((A[0]!=0 && ((A[0]*10 + A[1])%11==0)) ||
(A[0]==0 && ((A[1]*10 + A[2])%11==0)))
fprintf(outfp,"is divisible by 11.\n");
else fprintf( outfp, "is not divisible by 11.\n");
t--; fprintf(outfp, "\n");
}
}
substract()函数完成的是A-B的过程,其他都是控制台上读取输入指令和返回输出结果的操作。
通过此题我们看到,良好的数学功底对于CCC还是比较重要的。
鉴于商业软件系统使用字符串处理非常频繁,CCC也在其中大作文章,因为可以用来出题的商业应用场景比比皆是。
例如2009年初级组第4题,写好代码的同学基本上可以直接拿到真实环境中去用:
题目原文翻译如下:学生会需要在显示屏上用多行显示诸如"WELCOME TO CCC GOOD LUCK TODAY"字样,每一行最多可以容纳w个字符。你需要按照如下规则来显示这些文字:
1、每一行尽可能多的显示单词,且不能超过w个字符;
2、第一个词出现在行开头,如有多个词在该行,最后一个词显示在最后;
3、每行多余的空格需要显示在词与词中间并尽可能相同;
4、如果词与词中间的空格没有办法保持相同,最多的空格应该放在前面;
简单的翻译就是:如何对一段长文字美观地拆分到多行进行显示。
程序逻辑大概是这样:
接收一段文字;
通过检测字符串中的空格将其分割成一个一个的词,并用字符串数组存起来;
启动一个循环,到字符串数组中按照顺序找到前面的一些词,总长度刚刚小于w(每个词后面都追加一个空格);
在循环块中按照算法要求的4条规则将这些词排列好;
输出最终排列的结果;
限于篇幅,具体的代码略过,感兴趣的同学可以自己完成。
计算机相对人来说最大的优势是计算能力,用程序员的观点来看,就是计算机能够快速地通过循环来执行代码。
在计算机编程中,会写循环是最基本的技能。
在CCC竞赛中,为了检测参赛选手对于计算机语言的理解能力和逻辑思维能力,往往会采用比基础循环语句更高一级的自恋循环,之所以把它叫自恋循环,是因为它会无限次地调用自己,专业术语叫做递归编程。
递归编程容易理解,缺点是如果程序员一旦搞不清楚一个函数自恋自己到什么程度,边界条件稍微处理不当,就有可能造成无限循环,无休止自恋的结果就是堆栈溢出。
我们还是拿一道例题来说明吧,这是2015年初级组的最后一题:
题目原文翻译如下:一般3月14日叫做 π日,因为3.14正好是π的近似值。数学家用吃饼的方式来进行庆祝。假设你有n个饼,有k个数学家排着队来分饼吃,你需要写一个算法来把这n个饼分给这k个数学家,需要满足如下两个条件:
1.每个数学家至少有1个饼;
2.每个数学家分得的饼不能少于队列中前面的人分得的饼数。换句话说,饼数是一个递增序列;
此题看起来像是一道数学题,估计读友会觉得我有点特意往数学题方向上靠,其实不然,我们没有把这道题归为解数学题这一出题方向,尽管里面有数学家,也用到了数学逻辑的分类思维方法。
这是一道典型的递归算法编程题。
整个编程逻辑其实比较简单,借鉴了数学归纳法的一些递推思想:
1.定义一个递归函数getPiNo(int pieNo,int peopleNo,int firstPersonMinPieNo),有三个输入参数:
int pieNo:表示饼的总数;
int peopleNo:表示分饼的总人数;
int firstPersonMinPieNo:表示第一个人分得的饼数最小值;
2.如果要计算getPiNo(n,k,1),可以按照第一个人得到饼的数量进行分类;
第一类:第一个人分得1个饼,也就是后面k-1个人正好分得n-1个饼,并且k-1个人的第一个人最小可以分得1个饼。按照函数定义,正好有getPiNo(n-1,k-1,1)。程序走到这一分支直接返回getPiNo(n-1,k-1,1)即可;
第二类:第一个人分得2个饼,也就是后面k-1个人正好分得n-2个饼,并且k-1个人的第一个人最小需要分得2个饼。按照函数定义,正好有getPiNo(n-2,k-1,2)。程序走到这一分支直接返回getPiNo(n-2,k-1,2)即可;
......以此类推......
第n/k类:这是最后一个分类,因为如果第一个人超过n/k+1个饼,后面每个人都会超过n/k+1个饼,加起来就超过n个饼啦!第一个人分得n/k个饼,也就是后面k-1个人正好分得n-n/k个饼,并且k-1个人的第一个人最小需要分得n/k个饼。按照函数定义,正好有getPiNo(n-n/k,k-1,n/k)。程序走到这一分支直接返回getPiNo(n-n/k,k-1,n/k)即可;
在getPiNo(n,k,1)函数体内启动一个循环对前面所有类的得数求和后返回即可。因为在每个类里面都递归地调用了自己,只要控制好何时停止递归,算出答案不难。
只要把递归逻辑理解清楚,翻译成代码不难,需要注意哪些分类是叶子节点,在这些节点应该立即返回,终止递归。
同时为了提高程序运行的效率和性能,对于一些中间运行结果需要保留,以避免重复计算消耗CPU。
代码略过,感兴趣的同学可以根据上述逻辑完成编码。
"计算机要从娃娃抓起",三十多年前,邓小平高瞻远瞩地说出了这句名言。
三十多年后,看看我们的身边,3、4岁的娃娃们手机、电脑玩得溜溜的。
计算机上有太多好玩的东东,吸引着不少小朋友很早就进入这一领域,从小就开始学编程了,部分同学甚至觉得只要把编程学好了就可以独步武林天下,其他的学科例如数学可以不用花太多时间。
于是很多家长问我是不是可以只要把编程学好就行了。
我想上面的这份CCC数据分析报告其实已经给出了答案。
CCC让我们看到,没有扎实的数学功底,要想解决稍稍复杂一点的现实问题会比较困难,更不用说牵涉到复杂数学逻辑的算法了。
软件及互联网行业已经进入了开源软件盛行的时代,只要你能够想到的应用,一般都能够找到有人在做了,并且还是开源免费的,拿过来就能用。Rootofmath.com就很感恩这些开源软件的贡献者,他们大大地缩短了我们的研发周期。
开源软件让初级程序员进入的门槛大大减低,但如果没有扎实的数学功底,程序员向上发展的空间十分有限,其核心价值和竞争力会大打折扣。未来的程序员需要能够真正吃透开源软件才会比较吃香,否则碰到问题解决不了,也很难实现技术创新,在未来的时代可能会成为代码的搬运工。
滑铁卢计算机竞赛CCC让我们再次看到了数学教育的重要性。在参加数学竞赛学习的过程中,有些家长担心如果孩子在数学学习上花了时间却出不了成绩怎么办,CCC其实给我们指出了道路之一。数学好的孩子,可以东方不亮西方亮,即便没有在数学竞赛中拔尖,仍然可以在计算机、物理、经济、统计等领域拔得头筹。
至于选择什么编程语言参加CCC的问题,如果你已经学了某种语言很多年,有相当多的经验,尽管放心选择你熟悉的语言,因为每一种语言都有它适用的应用场景,自它诞生那天起,它就在为其所擅长的领域服务,今天很多人依然在用它,说明它具备了顽强的生命力。
如果你刚刚开始学习编程,如下经验供你参考:
如果你希望以后在一些科研院校做研究,建议你用Python。Python是一种脚本语言,门槛低,上手快,特别适合做科学研究和数值计算,缺点也恰恰来自于它的优点,因为过于简单,规范性不好,很少用来做大型商业应用系统;
如果你对自己的定位是以后进入大公司从事商业应用系统的研发,建议你用Java。虽然前期投入大一点,但是值得。尤其是Java 8引入的Stream API可以帮助你快速重用已有数据结构和组件完成排序和查找,瞬间实现大量代码,这一点在CCC中如果利用得当比较容易在编码时间上胜出;
如果你比较挑剔,控制欲望比较强烈,希望控制代码的方方面面,建议你用C/C++。C/C++的指针可以让你随心所欲地控制你的代码,出现诸如内存泄漏等性能问题也比较容易解决。缺点也同样来自于它的优点,因为控制得太细,你需要比别人花更多的时间来实现相同功能的代码。
计算机语言是相通的,熟悉一门语言再切换到另一门语言都不难,一通百通。
2020年滑铁卢CCC的初赛时间是2月12日。你,准备好了吗?
往期数据分析报告原创文章链接:
滑铁卢凯利Cayley(本文简称Cayley)数学竞赛,对16岁或十年级以下的学生开放。为纪念英国数学家凯利(Cayley ,1821-1895)而命名。
Cayley通常在每年二月中旬举行,北美比其他地区会提前一天考试。满分150分,分为A、B、C三部分,答题时间一个小时。全部为选择题,若空着不填,此题可加两分,打错则不拿分数。不提供中文版试题。
A部分10道题,每道题5分,简单基础题,有一部分是送分题;
B部分10道题,每道题6分,基础题,基础好的同学基本都可以答出;
B部分5道题,每道题8分,真正的竞赛题,尤其是最后两道题,难度比较大,顺利解出的话需要的步骤有时候会超过AMC10的题目。
先来看看2019年Cayley的参赛人数:
这是Cayley 23年来所有真题经过知识点为根的结构入库并通过数据分析得到的报告:
与9年级Pascal数学竞赛历年真题数据分析报告的数据进行对比后,我们可以看到:
Pascal对于基础数学知识点考察得比较多,例如基础运算、分数、百分数等;
Cayley则新增了对10年级新学内容例如直线方程(Linear Function)的重点考察,指数运算这一知识点也登上了排行榜第六名的位置。
方程应用(Equations)从Pascal第五名的位置攀升到Cayley的第二名,可以看出利用方程应用解题的能力随着年级的增加,重要性也逐步增加。
分数(Fractions)在Pascal和Cayley中保持了相同的名次:第三名,足见分数运算法则依然是9-10年级数学的重要考察点;
三角形角度(Triangle Angles)从Pascal的第六名上升到Cayley的第五名,排名稍有上升。
下面我们重点说明一下面积、直线方程、指数这三个知识点。
排在第一位的仍然是几何面积题,一共出现了61道,平均每套题2.5道。
将数据分析的范围限定在最后5道真正的竞赛题上面,我们发现Cayley很喜欢在难题部分出几何面积题,一共有17道难题落在了21-25题的区间,详细清单如下:
2005年第24题;
2013年第22题;
2012年第23题;
2009年第25题;
2010年第21题;
2008年第21题;
2007年第23题;
2004年第22题;
2004年第24题;
2003年第22题;
2003年第23题;
2002年第21题;
2002年第23题;
1998年第25题;
1998年第24题;
1997年第22题;
1997年第25题;
面积题的重要性前面一些文章当中已经有过详细说明,通过对Cayley历年真题进行分析后我们发现一个新的内涵:北美数学竞赛偏爱面积题的另外一个原因是面积题可以综合考察代数和几何的多方面知识,不光要求考生对于常用的一些几何公理、定理、推论以及应用比较熟悉,还要求考生可以活学活用代数相关知识(例如通过设未知数建立方程等)才能解出,因此面积题是综合考察代数和几何知识点完美的共同体,我想这也许是北美数学竞赛青睐几何面积题的另一个重要原因。
下面我们以Cayley1997年最后一道压轴题为例说明面积题是如何综合考察几何和代数知识点的:
题目原文翻译如下:在上图的三角形ABC中,BR = CR, CS = 3SA , AT/TB = p/q.如果三角形RST的面积是三角形TBR的两倍,则p/q为多少?
本题输入条件是三角形的边长关系和面积关系,输出条件是p/q的关系。
由于牵涉到未知数p和q,很容易想到此题的解题思路是通过面积建立等式,通过代数式变换,用面积的关系换取p和q的关系。
在几何里面,我们知道三角形的面积公式是:底*高/2;
而同高的两个三角形面积之比=底之比;
根据题目给的条件,两个边长之比很容易转换为面积之比;
而三角形RST面积为三角形TBR面积的两倍这一条件,初看不好构建等量关系,尤其是三角形RST的面积,底和高都没有,很难求出啊,很自然地想到将其中所有三角形的面积都用三角形ABC的面积来表示,从而就可以构建等量关系了。
因此我们可以假定三角形ABC的面积为k:
三角形ACR面积=三角形ABC面积/2(等高,面积之比等于底之比);
三角形SCR面积=三角形ACR面积*3/4(等高,面积之比等于底之比);
综合以上两个条件,立即得到:
三角形SCR面积=三角形ABC面积*3/8=3k/8;
同理可以得到:
三角形TBR面积=qk/[2*(p+q)];
三角形TAS面积=pk/[4*(p+q)];
三角形RST面积=三角形ABC面积-三角形TAS面积-三角形TBR面积-三角形SCR面积;
利用三角形RST的面积是三角形TBR的两倍这一条件立即有:
等量关系有了,面积都用p、q代数式表示出来了。
虽然有一个多余的变量k,但两边都可以同时除以k(因为k不等于0)约掉它:
这时候,代数恒等变换等技巧就有用武之地了,做一些化简,就可以得到答案了:
答案选E.
直线方程是9-10年级新学的内容,是解析几何(Analytic geometry)的基础,在Cayley中登上第四名的位置应该说是理所当然。
利用直线方程解题,是解析几何赋予我们最基本的工具和技能。
在Cayley中,直线方程的难题并不多。大部分都属于中等难度,29道直线方程的题目中,有17道落在了第10题至第20题的区间,有8道落在了第1题至第10题的区间。
将数据分析的范围限定在最后5道真正的竞赛题上面,我们发现Cayley仅有4道题落在了21-25题的区间,详细清单如下:
2009年第21题;
2001年第21题;
2001年第25题;
1998年第21题;
下面我们以2001年Cayley第21题来说明如何利用解析几何里面的一些基础知识点来快速解答直线方程的题目:
题目原文翻译如下:P在直线y=5x+3上面,Q的坐标是(3,-2),如果M是PQ的中点,则M所在的直线方程是下面哪一个?
此题需要利用中点坐标公式,即任意两点A(x1,y1),B(x2,y2)的中点M的坐标为((x1+x2)/2,(y1+y2)/2),注意是对应坐标相加后除以2。
(题外话:在教学中我们发现,很多同学记成了对应坐标相减后除以2,其实只要在纸上把A,B,M找出来,利用几何梯形中线的证明过程,对应坐标相加是很容易理解的)
一种解法是先假定有一点P(a,5a+3)在直线y=5x+3上面,利用中点坐标公式求出M的坐标为:
(1) x=(a+3)/2;
(2) y=[(5a+3)+(-2)]/2=(5a+1)/2
联合上面的(1)和(2),把a消掉就可以得到x和y的关系:
y=5x-7
因此答案选E;
另一种更加快速的解法是利用所求的中线必然与原来直线y=5x+3平行,因此其斜率一定为5,只需要在中线上找到一个点,加上这个斜率就可以写出这条直线方程了。
例如可以取P(0,3),利用中点公式得到PQ的中点M坐标为(3/2,1/2),通过M斜率为5的直线方程可以写作:
y-1/2=5*(x-3/2).
稍作化简就可以得到:y=5x-7.
因此答案选E;
指数符号是一步到位写出大数最简单有效的表述形式,也是滑铁卢数学竞赛系列中的一个考察重点。
高斯7年级排在第49名的位置(在那个年代还仅仅是平方数和立方数的考察);
高斯8年级快速上升到第16名的位置;
Pascal 9年级上升到第11名的位置;
Cayley10年级直接进入前六名排在了第6名的位置;
而且随着年级的增加,指数题目的难度也在逐步增加。
指数之所以如此重要,是因为它是学习指数函数、对数函数的基础,而这些都是将来微积分学习中很重要的基本函数,因此提前深刻掌握指数运算的各项法则有利于将来的学习得心应手。
Cayley的指数题难度都不大,作为基础考察的题目比较多,25道题中有18道题落在第1题至第10题的区间,6道题落在第11题至第20题的区间,只有1道题落在第21题至第25题的区间。
一般来说,指数部分的难题一般都会与数论、函数、概率等相关知识点结合起来出题,例如下面这道题,严格地说起来是一道数论题。
这是2010年Cayley的第25道压轴题:
题目原文翻译如下:Steve同学把一个计数器放在如图中0的位置。第一次顺时针移动1^1步到1,第二次顺时针移动2^2步到5,第三次顺时针移动3^3步到2.....以此类推,第n次顺时针移动n^n步。请问1234次移动以后计数器在哪个位置?
有经验的同学一看此题应该就会想到同余理论,不过随着n的增长n^n是一个很大的数,要把它算出来是比较困难的,好在我们只要找到它除以10以后的余数,就可以知道第n步顺时针移动了多少步,因为圆盘上只有10个数,移动10的任意倍数步都会回到原来出发的数。
所以接下来我们只要考虑n^n除以10以后的余数就可以了,也就是n^n的个位数。
而n^n的个位数是由n的个位数决定的。
n的个位数一共只有0,1,2,3,4,5,6,7,8,9这10种情况。
通过简单的测算,0,1,2,3,4,5,6,7,8,9这10个数n次方以后会呈现出以1,2,4为周期的特征,例如:
7^1,7^2,7^3,7^4,7^5,7^6,7^7,7^8的个位数分别为:
7,9,3,1,7,9,3,1......
而n^n的个位数是以10为周期的,由于1,2,4,10的最小公倍数为20,所以n^n的个位数是以20为周期的。
这句话用数学表达式来证明是这样的:
(20+a)^(20+a)
≡a^(20+a)
≡a^(4*5+a)
≡a^a (mod 10)
于是我们只要计算 1^1 +2^2 +3^3 +... +20^20 的个位数即可。
简单计算我们发现:
1^1+2^2+3^3+...+20^20
≡1+4+7+6+5+6+3+6+9+0
+1+6+3+6+5+6+7+4+9+0
≡94
≡4(mod 10)
( 注:≡表示模运算,即表示余数相等的意思,“mod 10”表示除以10的余数)
所以:
1^1+2^2+3^3+...+1234^1234
≡61*4+1221^1221+1222^1222+...+1234^1234
≡4+1+4+7+6+5+6+3+6+9+0+1+6+3+6
≡67
≡7 (mod 10)
答案选D。
指数类型的题目中,有很多是与数论相关的数的比较问题,只要注意化成同底或同幂后再进行比较,一般都可以轻松解出。
完成数据分析报告后我们发现,滑铁卢Cayley数学竞赛的题目其实并不难。
对于10年级同学来说,如果只是习惯了多项选择题的答题方式,即便在Cayley数学竞赛中可以获得130分以上的成绩,对于北美名校选拔的精英人才数学标准来说仍然是远远不够的。
事实上,滑铁卢自己也发现了多项选择题作为考试方式的弊端,从9年级开始增加了需要写步骤的Fryer(对应9年级)、Galois(对应10年级)和Hypatia(对应11年级),作为对Pascal(对应9年级)、Cayley(对应10年级)和Fermat(对应11年级)最好的补充。
在教学过程中我们发现,在加拿大本地接受数学教育的孩子都不爱写步骤,看见数学题想一想就随便选(或猜)一个答案完事的现象普遍存在,这应该与北美以多项选择题为主的标准化命题方式有直接关系。大部分考试都这样,孩子们自然而然就懒得在纸上写过程了。
这一现象导致的直接后果就是孩子们的数学成绩拿高分很难。没有步骤,直接心算给出答案,思路很容易跳跃,可能已经跳过了一个最关键的步骤,答案往往是错误的。
在实践中我们发现,孩子们的答案少写或多写一个零,小数点点错位置,漏掉了一个逻辑分支......这些都是很普遍的现象。
当我们在教学过程中强化步骤训练后,有的家长反映每次练习只要要求孩子在纸上写出步骤,答题正确率明显提高;而一旦放手让孩子们自己做题目,正确率又回到了解放前,因为孩子们没有写步骤答题的自觉性。
解题时写出严格步骤对于提高正确率来说效果是立竿见影的,还在苦于提高正确率的同学们可以尝试一下。
10年级数学成绩好的同学可以开始着手准备加拿大国手选拔赛COMC和滑铁卢的欧几里得数学竞赛了,这两个比赛都需要书写详细步骤。平时就注意加强解题步骤的训练,是培养严谨的逻辑思维能力和条理性尤为重要的一环,对于将来能够做出高质量的优秀论文也大有裨益。
因此我们强烈建议参加Cayley数学竞赛的同学,从这个阶段开始就应该有意识地加强解题步骤的训练,在参加Cayley的同时去参加Galois和Hypatia,为将来的学习和工作打下坚实的数学逻辑基础。
往期数据分析报告原创文章链接: