回 帖 发 新 帖 刷新版面

主题:第36次编程比赛第1题结果

// 所有测试时间的单位为毫秒。测试环境:winxp+vc6, release版本,PIII 1.13G
// 第1轮测试:
// 数据:n从2循环到100
ITER@第1楼:
    正确。总耗时: 280
    说明:n=1时错误,其他情况最后多了个.号
    
joekings@第2楼:
    正确。总耗时: 3084
    说明:最后多了个.号

ccpp@第3楼:
    正确。总耗时: 140
    说明:使用递归实现,程序非常简洁,速度也名列前茅。
    
gz80@第5楼:
    出现错误,错误处 i=10
    正确:0/1,1/10,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,3/10,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,7/10,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,9/10,1/1
    错误:0/1,1/:,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,3/:,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,7/:,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,9/:,1/1
    说明:没有考虑n大于等于10的情况
    总耗时: 0

asddg67@第6楼:
    出现错误,错误处 i=6
    正确:0/1,1/6,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,5/6,1/1
    错误:0/1,1/6,1/5,1/4,1/3,2/5,1/2,3/5,4/6,2/3,3/4,4/5,5/6,1/1
    说明:没有考虑4/6这种可约分的情况。
    总耗时: 0
    
neverPE @ 9:
    正确。总耗时: 130
    说明:时间复杂度应为O(n^2),但速度仍然显得较快,有点奇怪。

czarwind @ 10:
    出现错误,错误处 i=2
    正确:0/1,1/2,1/1
    错误:无结果

    总耗时: 0
    
瞬间移动 @ 11:
    出现错误,错误处 i=10
    正确:0/1,1/10,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,3/10,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,7/10,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,9/10,1/1
    错误:0/1,1/:,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,3/:,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,7/:,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,9/:,1/1
    说明:没有考虑n大于等于10的情况。
    总耗时: 0

火海时代 @ 12:
    出现错误,错误处 i=9
    正确:0/1,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,1/1
    错误:0/1,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,6/9,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,1/1
    说明:没有考虑6/9这种可约分的情况。
    总耗时: 0

liangbch @ 13-15:
    正确。总耗时: 80

zheni @ 16:
    出现错误,错误处 i=10
    正确:0/1,1/10,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,3/10,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,7/10,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,9/10,1/1
    错误:0/1,1/:,1/9,1/8,1/7,1/6,1/5,2/9,1/4,2/7,3/:,1/3,3/8,2/5,3/7,4/9,1/2,5/9,4/7,3/5,5/8,2/3,7/:,5/7,3/4,7/9,4/5,5/6,6/7,7/8,8/9,9/:,1/1
    说明:没有考虑n大于等于10的情况。
    总耗时: 0

hyerty @ 20:
    正确。总耗时: 583

xyhx @ 25:
    正确。总耗时: 210

szh @ 26:
    正确。总耗时: 2293
    
neverPE @ 27:
    正确。总耗时: 80

euc @ 28:
    正确。总耗时: 2294

liangbch @ 29-32:
    正确。总耗时: 180
    虽然有所改进,但由于程序更复杂,所以总的速度反而不如13楼的程序了。



// 第2轮测试:
// 数据:n从2循环到200
liangbch @ 13-15:(200)
    正确。总耗时: 971

neverPE @ 27:(200)
    正确。总耗时: 930

ccpp@第3楼:(200)
    正确。总耗时: 1192

neverPE @ 9:(200)
    正确。总耗时: 1242

xyhx @ 25:(200)
    正确。总耗时: 1591

liangbch @ 29-32:(200)
    正确。总耗时: 2234
    
ITER@第1楼:(200)
    正确。总耗时: 3456

hyerty @ 20:(200)
    出现错误,错误处 i=131
    错误:无结果

    总耗时: 940

joekings@第2楼:(200)
    出现错误,错误处 i=102
    错误:最后出现 100/101,}}}?101/102,101/102,1/1

    总耗时: 3344

euc @ 28:(200)
    正确。总耗时: 80403



// 第3轮测试:
// 数据:n从2循环到300
neverPE @ 27:(300)
    正确。总耗时: 3133

liangbch @ 13-15:(300)
    正确。总耗时: 4057
    
ccpp@第3楼:(300)
    正确。总耗时: 4418

neverPE @ 9:(300)
    正确。总耗时: 4576

xyhx @ 25:(300)
    正确。总耗时: 5587

liangbch @ 29-32:
    正确。总耗时: 7779
    
ITER@第1楼:(300)
    正确。总耗时: 46498

总的说明:
由于随着n的增加,时间复杂度递增非常快,所以本测试最多进行到n为300。
4楼、7楼、8楼和21楼由于与我给出的接口不一致,改起来太费事就没有测试,抱歉。

从上面的测试结果看,27楼neverPE的速度是最快的。因此,我宣布本次大赛的冠军为:[color=FF0000]neverPE[/color]。
另外,ccpp的程序速度与neverPE的也很接近,而且程序非常简洁,所以宣布ccpp获得优胜奖。



回复列表 (共24个回复)

21 楼

看了下最快的几个代码,喜欢 @ccpp 和 @xyhx 的方法,显然是利用法雷的内在规律来编,在大数据规模(大数)时理应快些,@xyhx 可以想办法利用数列来实现更加快速的链表,弄三个数组,一个保存对应值,高 16 位存分子,低 16 位存分母,另两个一个保存前项位置,一个保存后项位置,内存一开始就分好,这样应该能快些。

我原来想的方法用了双向链表,就直接上下乘 2、3 等往链表里添加,象楼主的例子

0/1,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,1/1

1/5, 乘 2 就已经超出范围,1/4 同样,1/3 上下同乘2,从 (2/6, 2/4) 中只有 2/5 (分子不变,分母变动 4-->6),到 1/2 时就能乘 3。这么能下来弄到 3/4。而后剩下的 4/5 就靠直接穷举得到。

比上面两位的方法慢些,因为有前插后插比较大小类操作(局部比较),而后最后的地方还有个穷举。

第 19 楼 @liangbch 如下
[quote]算法讨论:

 1.xyzh程序的特点:
  ....
 2)....在插入时,平均查找路径很短,这使得比同类排序算法(快速排序)更快。 
[/quote]

是错的,他没做两个分数的比较,只是检查是否超出 n,超出 n 了向后调整下,无所谓“查找路径”,只是简单的后插(可能调整下位置)。

22 楼

呵呵~都好厉害。。。。真是自愧不如,,什么时候有下次比赛啊?

23 楼

谢谢liangbch对我的程序的评价,我的程序确实比较差,没有考到很多情况
我是刚刚学完C++的,基本上没有学过数据结构(要恶补呀!!!)

24 楼

/*
任意相邻三项 a/b , c/d , e/f 满足(a+e)/(b+f) = c/d。
0/1                                                              1/1
                               1/2
                  1/3                       2/3
         1/4             2/5         3/5               3/4
    1/5      2/7     3/8    3/7   4/7    5/8      5/7         4/5 

*/
根据上面的结论,ccpp给出由两边求中间的递归算法,能否得到由第n项,n+1项,求出n+2项的公式,经过仔细思考,我找到了这个公式。
  假定相邻的三项为 a/b , c/d , e/f,则有:
        i=(n+b)/d;
       f=d*i-b;
       e=c*i-a;
  由于n阶法雷序列的第一项为0/1,第二项为1/n,则依此法可得到其余的每一项,下面为显示整个法雷序列的代码

void FareySequence2(int n, char farey[])
{
   int i,n1,n2,n3,d1,d2,d3;
   n1=0;   d1=1;
   n2=1;   d2=n;
   
   printf("%d/%d\n",n1,d1);
   printf("%d/%d\n",n2,d2);

   while (1)
   {
       i=(n+d1)/d2;
       d3=d2*i-d1;
       n3=n2*i-n1;
       
       if (n3==1 && d3==1) break;
    
    printf("%d/%d\n",n3,d3);
    n1=n2;   d1=d2;
    n2=n3;   d2=d3;
   }
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册