解决问题前的思考,欧拉计划27题的反思,3次优化和求解

来源:互联网 发布:新手编程软件 编辑:程序博客网 时间:2024/05/18 03:59

在遇到问题的时候,仔细思考,找到最好的方法,让计算机更快的完成任务是很重要的。

我们先来看一下这个问题:

欧拉曾发表过一个著名的二次公式:

n² + n + 41

这个公式对于0到39的连续数字能够产生40个质数。但是当 n = 40时,402 + 40 + 41 = 40(40 + 1) + 41能够被41整除。当n = 41时, 41² + 41 + 41显然也能被41整除。

利用计算机,人们发现了一个惊人的公式:n² − 79n + 1601。这个公式对于n = 0 到 79能够产生80个质数。这个公式的系数,−79 和1601的乘积是−126479。

考虑如下形式的二次公式:

n² + an + b, 其中|a< 1000, |b< 1000

其中|n| 表示 n 的绝对值。
例如, |11| = 11, |−4| = 4

对于能够为从0开始的连续的n产生最多数量的质数的二次公式,找出该公式的系数乘积。

这个题目还是很长的,具体的大家自己看。

我们如果不加分析,思路是这样的

a从-999到999循环{     b从-999到999循环         {                 n从0开始循环                  {判断n^2+a*n+b是不是质数如果是就一直循环,并且计数。

做题之前,我们可以先想一想,因为题目要求n从0开始连续产生质数,那么n=0的时候必须是质数才符合题意

n=0;n^2+a*n+b=b    ------------->我们可以得出结论,b一定是一个质数才符合题意。所以我们通过思考把b的范围给缩小了。b现在变成了0到1000以内的质数。

这个是我从网友那里得到的借鉴。

但是即使我这样优化了,效果也不是很明显;我们接着思考。


我们再来思考如果要更多的连续质数,n=1的时候也应该是一个质数吧,我们再来看一下n=1的情况

n=1;n^2+a*n+b=1+a+b--------------------->可以得出什么优化的结果呢?我们从上面知道b是一个质数,也肯定就是一个b+1肯定是一个偶数,最后结果要是质数,很显然a一定也是一个奇数才符合题意,所以我们把循环的次数缩小了一半。

我们可以

a=-999;a<999;a+=2;

但是结果还是用了3253second;


我们还要接着优化,其实a的范围可以更加的优化的!!

根据题目中给出的例子,结果肯定要比40大的,当n=40,要使最后的结果大于0

1600+40a+1000>0;

解一下:

a>-65的

我们把b 40以下的质数也去掉。

我们就进一步缩小了范围

程序如下:

use strict;use warnings;use bignum;my $start_time=time;my $big=1;my $first;my $second;my $n;my $result;my $i;my $flag;my $cout;my $first_X_second;my @special_number;#找1000以内的素数,并放到一个数组中@special_number=qw/2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997/;for($first=-65;$first<999;$first+=2)#a一定是奇数因为当n=1时,1+a+b要是质数的话,1+b一定以一个偶数,a只能是奇数,才有机会{foreach $second(@special_number)#第二个数一定要大于1的素数,因为n=0时,$result=$second;{$cout=0;for($n=0;;$n++){$result=$n**2+$first*$n+$second;if($result>0 && $result%2!=0){$flag=0;for($i=3;$i<$result**0.5+1;$i+=2)#写成**0.05{if($result%$i==0){$flag=1;last;}else{next;}}    if($flag==1)    {last;    }else    {    $cout++;    }}else{last;}}if($cout>$big){$first_X_second=$first*$second;$big=$cout;print "$first $second $cout\n";}}}print "$big $first_X_second \n";my $long=time-$start_time;print "$long\n";


结果如下:




也有半个多小时

明天接着优化

如果我们把判断质数的过程,改成先把所有的10万以内的指数都放在一个hash中,然后用查找的方法去验证是不是质数。这样又可以快很多。

具体的程序就不写了,留在这里,以后有时间再看!





















原创粉丝点击