[Project Euler] 来做欧拉项目练习题吧: 题目008

                                                [Project Euler] 来做欧拉项目练习题吧: 题目008

                                                                  周银辉 

 

问题描述: 

Find the greatest product of five consecutive digits in the 1000-digit number.

73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450

 

问题分析

上面列出了连续的1000个数字(虽然分成了10行书写,但第n行的结尾和第n+1行的开头也算连续的),找出最大的连续5个数的乗积。

这个题比较简单,基本思想是遍历,但可以想办法去掉一些不必要的运算,

典型的不必要运算有

1,五个数字中,其中一个是0;

2,abcdef代表数字数字串,从abcde前进到bcdef时,如果f不大于a,则后者乗积肯定没有前者大,所以可以免去计算bcdef的乗积,其将求五个数连乗的运算从995次减少到了318次 

 

参考代码:

#include <stdio.h>
int test(char * str)
{
int max = 0, temp, i;
char *start=str, *end;
for(start = str; *(end=(start+5))!='\0'; start++)
{
//如果遇到0,则应该跳过0附近的运算
//应该跳过5个数字,因为start++还要加1,所以这里加4
if(*end == '0')
{
start += 4;
continue;
}
//如果将当前的5个数字看成一个队列的话,
//每前进一步,会在末尾添加一个数字,并舍弃头部的数字
//而中间4个数字相同,所以比较添加的数字和舍弃的数字
//如果添加的数字不大于舍弃的,那么也没必要计算了
if(start > str && *end<=*(start-1))
{
continue;
}
temp = 1;
for(i=0; i<5; i++)
{
temp *= (*(start+i)-48);
}
if(temp>max)
{
max = temp;
}
}
return max;
}
int main()
{
char * numStr = 
       "73167176531330624919225119674426574742355349194934\
96983520312774506326239578318016984801869478851843\
85861560789112949495459501737958331952853208805511\
12540698747158523863050715693290963295227443043557\
66896648950445244523161731856403098711121722383113\
62229893423380308135336276614282806444486645238749\
30358907296290491560440772390713810515859307960866\
70172427121883998797908792274921901699720888093776\
65727333001053367881220235421809751254540594752243\
52584907711670556013604839586446706324415722155397\
53697817977846174064955149290862569321978468622482\
83972241375657056057490261407972968652414535100474\
82166370484403199890008895243450658541227588666881\
16427171479924442928230863465674813919123162824586\
17866458359124566529476545682848912883142607690042\
24219022671055626321111109370544217506941658960408\
07198403850962455444362981230987879927244284909188\
84580156166097919133875499200524063689912560717606\
05886116467109405077541002256983155200055935729725\
71636269561882670428252483600823257530420752963450\
";
printf("%d\n", test(numStr));
return 0;
}

 

 

posted @ 2011-01-25 18:54 周银辉 阅读(1752) 评论(11) 编辑 收藏

 回复 引用 查看   
#1楼 2011-01-26 09:50 年华不再      
请问下,有谁看到这里是有1000个数的,反正我是只看到20个数,整个一行为一个数字,标点都不打
 回复 引用 查看   
#2楼 2011-01-26 10:03 DiggingDeeply      
@年华不再
1000位的一个数字

 回复 引用 查看   
#3楼 2011-01-26 10:13 DiggingDeeply      
这题我过的有点巧,直接搜索含有9的字串,没有999,99的有个99879。
如果99879换成97989,那就看含有单个9的字串了。还好串不长,基本上可以目测。
LZ的做法很好,还有我有一点基于LZ做法的改进:
if(*end=='1')
{
start++;
continue;
}

 回复 引用 查看   
#4楼 2011-01-26 11:09 devil0153      
花了4天时间把level1过了:)
我觉得level1以下的题目几乎都可以通过暴力的方式解决,对于现代的计算机实在小菜一碟,当然,ProjectEuler的题目也是循序渐进的,先给你点甜头,再逐步加大难度,让暴力失效,比如我做到第18题,真的就是暴力计算,丝毫不考虑性能和内存,看了下面的NOTE跳转到同样的第67题,解18题的思路就完全不可行了~~

 回复 引用 查看   
#5楼 2011-01-26 11:11 devil0153      
建议LZ建立一个Project Euler的小组,让志同道合的园友加入进来:)
 回复 引用 查看   
#6楼 2011-01-26 11:37 耀哥      
顶起。园子里应该多这样的文章。
 回复 引用 查看   
#7楼[楼主] 2011-01-26 12:41 周银辉      
@年华不再
"上面列出了连续的1000个数字(虽然分成了10行书写,但第n行的结尾和第n+1行的开头也算连续的)"


 回复 引用 查看   
#8楼[楼主] 2011-01-26 12:43 周银辉      
@devil0153
暴力就没意思了嘛~~~ 对自己的锻炼也会减少。这些题目是拿来锻炼自己的,又不是被强加的家庭作业...

 回复 引用 查看   
#9楼 2011-01-26 12:51 devil0153      
引用周银辉:
@devil0153
暴力就没意思了嘛~~~ 对自己的锻炼也会减少。这些题目是拿来锻炼自己的,又不是被强加的家庭作业...

LZ说的没错,完全赞成,只不过我偷偷浏览了后面的题目,有些是跟前面类似的题目但是完全无法使用“暴力”,所以我就想把前面的进程加快一些,到后面的题目再来研究“非暴力”,纯属个人喜好:)

 回复 引用 查看   
#10楼[楼主] 2011-01-26 12:55 周银辉      
引用devil0153:
花了4天时间把level1过了:)
我觉得level1以下的题目几乎都可以通过暴力的方式解决,对于现代的计算机实在小菜一碟,当然,ProjectEuler的题目也是循序渐进的,先给你点甜头,再逐步加大难度,让暴力失效,比如我做到第18题,真的就是暴力计算,丝毫不考虑性能和内存,看了下面的NOTE跳转到同样的第67题,解18题的思路就完全不可行了~~

另外,我刚才看了下18题,您可以利用二叉树和记忆式搜索建立缓冲区(避免重复运算),在我的笔记本上(2.4G双核)用很短的时间就可以计算出答案了:
ZHOU-YHmatoMacBook-Pro:Temp zhouyh$ time ./018.exe
result is 1074

real 0m0.013s
user 0m0.001s
sys 0m0.003s
具体的解法我会在讲到18题时详细说。

 回复 引用 查看   
#11楼 2011-01-26 17:33 类型安全的心      
我觉得吧,算法第一条应该是尽量简单。而不管是不是暴力。如果暴力算法可以很明了的解决问题,也未尝不可。
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1944847 PQQyS/c5HRw=