欧拉工程第44题:Pentagon numbers

getit
题目链接:https://projecteuler.net/problem=45
题意:
Pn=n(3n1)2 ,满足这个通项的数,pi pj,如果 pi pj 的和差也在这个通项中,则求出最小的 pi-pj

思路:
题目很简单的,最主要的问题是,如何确定上界,上界过大时间运行比较长。
先不考虑上界问题:
1.求pi,求pj
2.判断pi+pj,pi-pj是否在通项中
3.求出最小的差值

当然可以自己设置一个很大的数来作为上界。

那么,可以根据 Pn=n(3n1)2 来确定D=pi-pj的最小值所满足的条件吗?

根据设置上界的方法,我发现这个最小的D就是第一个D,反过来说就是随着n的增大,D是会变大,也就是差值变大。

下面考虑 P(n+1)P(n)=3n+1 ,当n很大时候,相邻两个数的值是 3n+1 ,比如:n=100万,差值就是300万,然而这个两个数所在的坐标斜率也是三百万。这个很大了。。。
画下图看看
这里写图片描述
这个是x和y的散点图,有一万个点,所有看着像是线了,根据这个图可以看到是上升的趋势,仔细看y轴1.5e8,x轴最大才是1W,已经很大了。
下面的图是相邻两个点的斜率,在1000时的斜率是30000
这里写图片描述
根据上面两点可以知道,相邻连续的两个点的差值随着n的增加而增大,若不是相邻的两个点,则差值会更大,问题让我们求得是最小的差值,则最小的差值就是第一个差值。

所有只需求出第一个满足条件的差值。

Java代码:

package projecteuler41to50;

import java.util.Date;

class level44{
    void solve2(){
        int minD=9999999;
        int D=0;
        for(int i=2;;++i){
            for(int j=1;j<=i;j++){
                int pi=getPentagonal(i);
                int pj=getPentagonal(j);
                // pj<pi
                if(isPentagonal(pj+pi) && isPentagonal(pi-pj)){
                    D=pi-pj;
                    if(D<minD){
                        minD=D;
                        System.out.println(minD);
                        return;
                    }
                }
            }
        }

    }

    void solve(){
        int Max_Value=3000;

        int minD=9999999;
        int D=0;
        for(int i=1;i<=Max_Value;++i){
            for(int j=i+1;j<Max_Value;j++){
                int pi=getPentagonal(i);
                int pj=getPentagonal(j);
                // pj>pi
                if(isPentagonal(pj+pi) && isPentagonal(pj-pi)){
                    D=pj-pi;
                    if(D<minD){
                        minD=D;
                        System.out.println(minD);
                        return;
                    }
                }
            }
        }
        System.out.println(minD);
    }
    int getPentagonal(int index){
        return index*(3*index-1)/2;
    }
    boolean isPentagonal(int num){
        int delt=1+24*num;
        if(isSquare(delt)){
            int member=(int) (1+Math.sqrt(delt));
            if(member%6==0 && member/6>0)
                return true;
        }
        return false;
    }
    boolean isSquare(int num){
        int n=(int) Math.sqrt(num);
        if(n*n==num)
            return true;
        return false;
    }
}
public class Problem44 {

    public static void main(String[] args){
        Date beginTime=new Date();
        new level44().solve2();
        Date endTime=new Date();
        Long Time=endTime.getTime()-beginTime.getTime();
        System.out.println("Time="+Time/1000+"秒"+Time%1000+"毫秒");
    }
}

solve 是手工设置的上界+第一个D
solve2是直接根据第一个D求得
结果:

5482660
Time=0秒37毫秒

由于上界设成3000,两个运行时间差不多的。
此时对于的i,j是:1020,2167

Python代码:

from time import time
import math
def getPentagonal(index):
    return index*(3*index-1)/2

def isPentagonal(num):
    index=(math.sqrt(24*num+1)+1)/6
    if index==int(index):
        return True
    return False



t1=time()
for i in range(2,3000):
    for j in range(1,i):
        plus=getPentagonal(i)+getPentagonal(j)
        minus=getPentagonal(i)-getPentagonal(j)
        if isPentagonal(plus) and isPentagonal(minus):
            print minus

t2=time()
elapsed = t2 - t1

print(str(round(elapsed, 5)) + " seconds")   

结果:

5482660.0
15.122 seconds

根据Java程序写的,,,上面的Java程序判断了最小的D,其实不需要的,因为第一个D就是结束了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值