Online Judge判题结果解析

正确(AC: Accept 即表示程序通过)

恭喜你了

答案错误(Wrong Answer)

答案不对,仅仅通过样例数据的测试并不一定是正确答案。如果你的程序有错误自然只能改正后再交

但是初学者还有一个常见的错误是计算结果已经正确了,但是输出格式不按样例来导致错误。

本学校OJ上一个结果如下: 

263281 1505020241
C
答案错误
1084
1
C/Edit 243 B 2015-11-25 17:18:29

点击答案的地方可以一定程度上帮助你发现问题所在。

例如看到下面的信息:

=================/test.out
Right:
8

-----------------
Your:
p=8

=================

很明显这位同学画蛇添足,多输出了"p="

再如下面的结果,明显搞错了大小写。

=================/harmonious.out
Right:
triangle

-----------------
Your:
Triangle

=================

编译错误 (Compile Error Error,简称CE)

246070 1505020146
C
编译错误(点击看详细)
0
0
C/Edit 432 B 2015-11-07 17:00:10

 提交可以看到上面的结果,可以在 编译错误(点击看详细) 点击看到更详细的信息。

犯这种错误的原因一般有:

1.  你在本地(就是你的编程环境下)都没有编译成功就直接提交了,这种做法是错误的。必须本地编译通过,而且要运行通过了你的样例和额外的测试数据后才能交

2. 你本地的程序正确,但是你提交时的拷贝漏掉了一些内容

3. 编译器选择错误。在提交(submit)时可以选择C/C++/JAVA编译器,选择错了有时候会导致编译错误。大部分情况下,C程序选择C或C++编译器都没有问题。但是C++程序选择C编译器一般都会有问题。

4. 编译器不兼容。你本地的程序编译通过,但是你的程序提交到服务器,服务器的编译器跟你的不兼容,导致你的程序编译出错。一般说来,这种情况比较少见

格式错误 (Presentation Error,简称PE)

这种情况下一般意味着数据都对了。但是可能多了/少了空格, 或者多了/少了 换行。

示例一:实验三问题 B: 最大数与最小数之差, 下面的代码明显多出了一个空格

1 printf("%d \n",max-min);

 

 示例二:实验四问题 H: 两数之和。 注意从第9行跳至第16行,会多一次换行。

复制代码
 1  while (scanf ("%d %d",&sum,&n)!=EOF)
 2     {        
 3         for (...)
 4         {
 5             for (.....)
 6             {
 7                 if (...)
 8                 {
 9                     printf ("%d %d\n",a,b);
10                     goto out;
11                 }
12             }
13 
14         }
15         printf ("No Solution");
16 out:
17         ;
18         printf ("\n");
复制代码

 

示例三: 实验五问题 D: 实验4-1:编求素数的函数,题目要求是“多个结果之间由空行隔开”,样例也非常清晰,但是有些同学就是无视于此,忘记空行,导致PE错误。

 时间超限 (TLE,Time Limit Exceeded,超时)

每一个程序给了一个时间限制,最常见的是1秒,如果你的程序在规定时间内没有运行完毕,可能就会得到一个TLE.

导致TLE的主要原因有:

1. 你程序所用的方法不够快,运行效率低,导致超时。

OJ上通常10^8规模的计算就需要1s,如果你的循环体运行总数 * 测试数据数量达到了该数量级,你的程序很可能超时。

典型的例子如实验四的质数分解,有些同学还适用如下低效率的做法导致超时。更好的做法是 i *i <=n

for(i=2;i if(n%i==0)
  break;
}

2. 你的程序出现了死循环。

例如实验二B, 有同学试图用循环来做,很遗憾的 循环结束条件!='\0'写错了,程序一直运行导致TLE.

 for (i=0;getchar()!='\0';i++);

输出超限(Output Limit Exceeded)

 

一般是输入控制没有处理好,更少见的情况是涉及输出的地方没有控制好(如死循环);最终导致输出的信息过多超出了限制。

 

 

问题 G: 进制转换

题目描述

 给出一个十进制的正整数,输出它的二进制表示。

输入

有多行数据,每一行一个正整数,整数值在[1-100000000]之间。

输出

输出相应的二进制数.每一行输出对应每一行输入

样例输入

3 4

样例输出

11 100
 
下面是一个能产生“输出超限”的代码
复制代码
 1 int main()
 2 {
 3     int n,a;
 4     int p[31];
 5     for (;scanf ("%d",&n);)
 6     {
 7 
 8         ...
 9         while (j--)
10             printf ("%d",p[j]);
11         printf ("\n");
12 
13     }
14     return 0;
15 }
复制代码

原因非常简单,正确的控制应该是

 scanf ("%d",&n) != EOF
这个同学的写法导致循环一直执行,不断产生输出,从而输出超限。
更详细地解说见 http://www.cnblogs.com/4bytes/p/4192329.html
 
示例二

问题 C: 实验4-3:编求阶乘的函数

输入

每行输入一组测试数据:2个正整数m和n。m与n均为非负整数。

m和n均为0时,结束输入。

输出

...

样例输入

11,10
10,9
5,2
5,0
0,5
5,5
0,0

下面的代码会产生输出超限

复制代码
1 int main()
2 {
3    int m, n;
4    float y;
5    while(scanf("%d%d", &m, &n) != EOF) {
6       if(m == 0 && n == 0)
7          break;
8       printf(...);
9    }
复制代码

错误的原因是两个%d之间缺了一个逗号,但为什么会导致输出超限呢?因为输入的逗号scanf无法接收,scanf的输入流一直处于错误状态,所以无法继续接收下面的数据。

比如输入"11,10", m的结果是10,但随后的逗号scanf无法处理,出错,n此时的值是随机值。 scanf返回1,不等于EOF.第5行为真,执行第8行。然后回到第5行,此时,输入流处于错误状态,scanf只会返回0,依然不等于EOF,继续为真,又执行第8行,如此往复输出导致输出超限。感兴趣的同学可以用下面的代码运行然后输入"11,10"

复制代码
 1 #include 
 2 int main()
 3 {
 4    int m, n;
 5 
 6    int ret;
 7    while((ret =scanf("%d%d", &m, &n)) != EOF) {
 8       if(m == 0 && n == 0)
 9          break;
10       printf("%d %d %d\n",ret, m, n);
11    }
12    return 0;
13 }
复制代码

 再给出一段scanf的说明

 “When a matching failure occurs, scanf returns immediately, leaving the first non-matching character as the next character to be read from the stream. The normal return value from scanf is the number of values that were assigned, so you can use this to determine if a matching error happened before all the expected values were read.”

 

在HUST OJ,  如果你的输出到了标准输出的两倍就会产生该错误,笔者曾经有一个程序因为溢出错误导致了很大的整数输出,正确的答案是数据规模很小,最后judge判题的结果是输出超限,而不是wrong answer。

 

Runtime Error (RE) : 运行时错误

这个一般是程序在运行期间执行了非法的操作造成的。下面是常见的错误类型: 

1. 数组下标越界或指针指向无效地址

学校OJ的辅助信息有

“Runtime Error:Segmentation fault
辅助解释:
Segmentation fault:段错误,检查是否有数组越界,指针异常,访问到不应该访问的内存区域”
 

有时候,还有如下的辅助信息

Runtime Error:[ERROR] A Not allowed system call: runid:262244 callid:20
 TO FIX THIS , ask admin to add the CALLID into corresponding LANG_XXV[] located at okcalls32/64.h ,and recompile judge_client
辅助解释:
A Not allowed system call: runid:262244 :使用了系统禁止的操作系统调用,看看是否越权访问了文件或进程等资源”

 示例代码1, 第二行n应该是&n(指针类型).

1 int n, h, i, s;
2 scanf("%d",n);

 示例代码2, 这个代码更为诡异,scanf多一个%d,会导致指针误用,但是CB在编译时可以提供警告,被同学放过了。

复制代码
1     int a,b,c,n;
2    
3     scanf("%d",&n);
4     while(n>0)
5     {
6         scanf("%d%d%d%d",&a,&b,&c);
复制代码

 

示例代码3, 下面代码的问题在于第一行的数组开小了,如果n比较大, i的值绝对会超过9。

复制代码
1 int n, a[10] = {0}, i;
2 i = 0;
3 do
4 {
5    a[i++] = n % 2;
6    n = n / 2;
7 } while(n > 0);
复制代码

 再如下面的代码,n无初值,当然可能越界。

复制代码
1     int n,i;
2     int fib[40] = {1,1};
3     for(i=2; i)
4     {
5         fib[i] = fib[i-1]+fib[i-2];
6     }
复制代码

 

2. 除以0

学校OJ的辅助信息有

“Runtime Error:Floating point exception
辅助解释:
Floating point exception:浮点错误,检查是否有除以零的情况”
 

  如下的示例代码,第3行j=2应该是i=2, 所以i没有赋初值(可能是负的,也可能是0)。总而言之,第4行就有i值为0的可能,除0的情况就出现了。

复制代码
1         int i,j;
2         scanf("%d",&j);
3         for(j = 2; i * i <= j; i ++)
4             if(!(j%i))
5             {
6                 break;
7             }
复制代码

 3. 开了大数组

示例如下,数组太大了,函数内的数组建议空间不要超过2MB,实在需要大数组可以定义在函数的外面。

复制代码
1 int main()
2 {
3     int a[10000000], m, n, x, i = 0;
4     
5     return 0;
6 }
复制代码

4. 递归导致的栈溢出

下例是求斐波那契数列的代码,但是第12行的输入不符合要求,导致-1也会处理,fib(-1)会导致递归反复进行下去耗尽栈空间

输入

输入包括若干行,每行输入一个正整数n,若输入-1则结束。

输出

对于每行输入的n的值,对应输出f(n),每个输出单独占一行。若输入是-1,则不输出任何结果。

样例输入

6
7
8
9
-1
复制代码
 1 #include 
 2 int fib(int n)
 3 {
 4     if(n == 0 || n == 1)
 5         return 1;
 6     else
 7         return fib(n-1)+fib(n-2);
 8 }
 9 int main (void)
10 {
11     int n;
12     while(scanf("%d",&n) != EOF)
13         printf("%d\n",fib(n-1));
14     return 0;
15 }
复制代码

 5 调用库函数但不满足前提条件

例如两次调用栈的pop函数,但是第二次调用之前已经是空栈。

 6 嫁接的错误

 非常少见,但是有可能。HUST OJ因为是TLE,反而报出了RE

 ACCESS_VIOLATION 您的程序想从一些非法的地址空间读取或向其中写入内容。一般例如指针、数组下标越界都会造成这个错误的。  
 ARRAY_BOUNDS_EXCEEDED 您的程序试图访问一个超出硬件支持范围的数组单元。   FLOAT_DENORMAL_OPERAND 进行了一个非正常的浮点操作。一般是由于一个非正常的浮点数参与了浮点操作所引起的,比如这个数的浮点格式不正确。   FLOAT_DIVIDE_BY_ZERO 浮点数除法出现除数为零的异常。  
 FLOAT_OVERFLOW 浮点溢出。要表示的数太大,超出了浮点数的表示范围。   FLOAT_UNDERFLOW 浮点下溢。要表示的数太小,超出了浮点数的表示范围。   INTEGER_DIVIDE_BY_ZERO 在进行整数除法的时候出现了除数为零的异常。   INTEGER_OVERFLOW 整数溢出。要表示的数值太大,超出了整数变量的范围。  
 STACK_OVERFLOW 栈溢出。一般是由于无限递归或者在函数里使用了太大的数组变量的原因。   
...... 其他错误,包括C++标准库/STL运行时库错误等,这里不再举例。  

内存超限(Memory Limit Exceed,MLE)
一般原因是你开的数组太大了,或者题目对给程序的存储限制比较厉害。
比如下面的题目

1697: 寻找宝藏

时间限制: 1 Sec  内存限制: 128 MB
某个同学定义数组int c[100000000];  你算一下需要多少空间。有没有超128MB的限制?

你可能感兴趣的:(知识点)