程序设计竞赛专题挑战教程
上QQ阅读APP看书,第一时间看更新

1.5 蓝桥杯软件类大赛的评测系统

本书的例题和习题选自蓝桥杯大赛官网题库(在本书中简称lanqiaoOJ),lanqiaoOJ中有历年真题和一些训练题。

lanqiaoOJ里面的“判题机器人”如何判断你提交的代码是否正确?

能否直接通过看代码的方式,检查每一行代码的逻辑的正确性?这几乎是不可能实现的,因为看别人的代码极其痛苦,往往会让人晕头转向。即使是常年进行计算机编程教学的老师在检查别人的代码时也不例外,像程序设计这样的题目,如果改卷的老师不是用机器验证,而是手动批阅,将很难打分。

所以lanqiaoOJ中的“判题机器人”如果看不懂你提交的代码,它干脆就不看代码,而是直接检验你提交代码的正确性。这一方法简单粗暴(即用黑盒测试),步骤如下。

(1)准备好标准测试数据,包括输入data.in和对应的输出data.out。

(2)运行你提交的代码,读入输入数据data.in,产生输出数据my.out。

(3)如果超出限定时间,代码还没运行结束,那就是没有产生输出,则判错。

(4)对比data.out和my.out,如果完全一样,则判为正确,否则判错。

蓝桥杯软件类大赛的判题规则允许选手得部分分数。一道题包含多组测试数据,一般是10组,每组占10%的分数。有的测试数据比较简单,容易通过,能够让选手得一些分数。

下面说明lanqiaoOJ的使用方法。输入链接地址(www.lanqiao.cn/problems)之后,出现图1.1所示的页面,单击“标签”,然后按“年份”或其他算法分类查询题目。

图1.1 lanqiaoOJ题库

做lanqiaoOJ中的题目时,需要输入相应的代码让“判题机器人”判断。下面分别就结果填空题(以下简称填空题)和编程大题举例说明。

1.结果填空题

例题1-1.平方和

2019年(第十届)省赛,填空题,lanqiaoOJ题号599

【题目描述】小明对数位中含有2、0、1、9的数字很感兴趣,在1到40中这样的数包括1、2、9、10至32、39和40,共28个,它们的和是574,平方和是14362。注意,平方和是指将每个数分别平方后求和的结果。请问,在1到2019中,所有这样的数的平方和是多少?

✧ 提示:这一题的链接是https://www.lanqiao.cn/problems/599/learning/,题号599。本书后面的题目只给出题号,省略完整的链接。

这是一道填空题,只需要写出答案即可,不过仍需要编写代码以求得答案,这一题的求解过程参见2.1.4小节“巧用Python”中的例题2-12“平方和”。

(1)编写并提交代码。这一题的答案是2658417853,在lanqiaoOJ中的测试方法如图1.2所示。

图1.2 测试lanqiaoOJ 599题

单击页面下方的“提交检测”,系统返回测试结果。

(2)查看错误提示。单击页面左边的时钟符号,可以看到自己提交的这一题的记录,如图1.3所示。单击“FAIL”可以看到判题说明。

图1.3 lanqiaoOJ 599题的测试记录

(3)看题解。lanqiaoOJ的一个优点是提供了题解功能,能看到其他人的题解。单击页面左边的“答 题解”,可以看到此题的各种编程语言的题解,非常方便。单击此题的“Python3”题解,可以看到有123个题解,如图1.4所示。读者做题后也可以发布自己的题解,方便别人学习你的解题思路。

图1.4 lanqiaoOJ 599题的“Python3”题解

2.编程大题

编程大题有多组测试数据。下面用一道题说明“判题机器人”如何用这些数据测试出你的代码的正确性。

例题1-2.刷题统计

2022年(第十三届)省赛,lanqiaoOJ题号2098

时间限制:1s 内存限制:256MB

【题目描述】小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做a道题,周六和周日每天做b道题。请你帮小明计算,按照计划他将在第几天实现做题数大于等于n题?

【输入格式】输入一行,包含3个整数abn

【输出格式】输出一个整数代表天数。

【评测用例规模与约定】对于50%的评测用例,1≤a, b, n≤106;对于100%的评测用例,1≤a, b, n≤1018

下面的代码可以简单地模拟题目的操作:周六、周日每天做b道题,周一到周五每天做a道题,累计到n题时输出天数。

 1  #include<bits/stdc++.h>
 2  using namespace std;
 3  int main(){
 4      long long a,b,n;   cin>>a>>b>>n;    //注意用long long
 5      long long sum=0,day=0;
 6      while(sum<=n){
 7          day++;
 8          if(day%7==6||day%7==0) sum+=b; //周六、周日每天做b道题
 9          else                   sum+=a; //周一至周五每天做a道题
10      }
11      cout << day;
12  }

提交代码后,只能通过50%的测试。这意味着若是10分的题,只能得到5分。

为什么只能通过50%的测试?因为代码的运行效率低。在while循环中,每循环一次,day加1,所做题目数量累加为sum,直到sum>n,这样做效率非常低。本题要求“时间限制:1s”,对于100%的数据,1≤a, b, n≤1018,上面代码的运行时间显然会超过1s。

判题机器人会将超时的代码判为“错误”,例如下面这组测试数据:

7089 7494 500000014592.

答案是69399007,即while循环了69399007次,运行时间约2s,超时了。

这一题如果要100%通过测试,可参见8.1节“模运算”中关于该题的解析。