• PE2 Even Fibonacci numbers(最大菲波那列偶数)


    本系列前言PEProject Eluer)是学Mathematica(以后我简称Mma)接触到的,不用提交代码,只用提交答案的答题网站。PE的题目会给出C++Mma代码实现,以此学习Mma(已经被它的简洁给折服了..)。

     

    题目

    Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

    1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

    By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

    https://projecteuler.net/problem=2

    分析

     

    题目求由不小于四百万的偶数之和。

    Fibonacii算法复习

    这里涉及到求Fibonacii数列的算法,一般来说有如下几种:

    n  二分递归法:用递推公式,Fn = F(n-1)+F(n-2)O(2n)

    n  线性递归法:用态规划思想,保存解。TimeO(n) PlaceOn

    n  迭代:On),由于迭代法完胜递归法,前两种方法平时基本不用去使用;

    n  其他方法(二分矩阵、公式法

    Code部分贴上前三种方法,作为复习Fibonacii算法(我只会这三种)。

    偶数求和分析:

    1.     暴力法:循环到大于4000000结束,依次算出每个数的Fn,偶数则加和。On

    int FibEvenSum1(intlimit){

       int sum = 0;

       int a = 0;

       int b = 1;

       while (a<limit)

       {

           int c = b;

           b += a;

           a = c;

           if (a % 2 == 0) sum += a;

           cout << "sum:" << sum << endl;

       }

       return sum;

    }

    2.     Mma列举出几个Fib看看(Mma实在太适合干这个了。。。)

    I Fibonacci@Range[1, 20]

    O:  {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765}

    得到规律:其中偶数的序列为:F3F6F9…….所以可以从这里入口优化。

    int FibEvenSum2(intlimit){

    int sum = 0;

    int a = 1;

    int b = 1;

    int c = a + b;

    while (c<limit)

    {

         sum += c;

         a = b + c;

         b = c + a;

         c = a + b;

         cout << "sum:" << sum << endl;

    }

    return sum;

    }

    效率提高2倍,还有更beautify….

    3.  再次用Mma观察

    I :              Fibonacci@Range[1, 20] // Select@EvenQ

    O:             {2, 8, 34, 144, 610, 2584}

    设新数列为EnEn = 4*En-1+En-2

    如何来的呢?Fn  =  Fn-1+Fn-2

                         =  2Fn-2+Fn-3

                            =  4F(n-3) + F(n - 6)

    用这个递推公式优化后,效率在2的基础上提高3

    int FibEvenSum3(intlimit){

    int a = 0;

    int b = 2;

    int c = 0;

    int sum = 0;

    while (c < limit){

         a = 4 * c + b;

         b = 4 * a + c;

         c = 4 * b + a;

         if (c < limit)sum += c;

         if (b < limit)sum += b;

         if (a < limit)sum += a;

         cout << "sum:" <<sum <<endl;

    }

     return sum;

    }

    Code

    #include <iostream>
    using namespace std;
    int FibEvenSum1(int limit);
    int FibEvenSum2(int limit);
    int FibEvenSum3(int limit);
    int main(){
    
        int d = FibEvenSum1(4000000);
        cout << endl;
        int f = FibEvenSum2(4000000);
        cout << endl;
        int r = FibEvenSum3(4000000);
        return 0;
    }
    
    
    int FibEvenSum1(int limit){
        int sum = 0;
        int a = 0;
        int b = 1;
        while (a<limit)
        {
            int c = b;
            b += a;
            a = c;
            if (a % 2 == 0) sum += a;
            cout << "sum:" << sum << endl;
        }
        return sum;
    }
    /*1 1 2 3 5 8 13 21 34 每三个数出现一个偶数*/
    int FibEvenSum2(int limit){
        int sum = 0;
        int a = 1;
        int b = 1;
        int c = a + b;
        while (c<limit)
        {
            sum += c;
            a = b + c;
            b = c + a;
            c = a + b;
            cout << "sum:" << sum << endl;
        }
        return sum;
    }
    
    int FibEvenSum3(int limit){
        int a = 0;
        int b = 2;
        int c = 0;
        int sum = 0;
        while (c < limit){
            a = 4 * c + b;
            b = 4 * a + c;
            c = 4 * b + a;
            if (c < limit)sum += c;
            if (b < limit)sum += b;
            if (a < limit)sum += a;
            cout << "sum:" <<sum <<endl;
        }
         return sum;
    }
    EvenFibSum

     

    #include <iostream>
    
    using namespace std;
    __int64 fib(int i);
    __int64 fib2(int n, __int64 & prev);
    __int64 fib3(int n);
    long main(){
    
        cout << fib(10);
        cout << fib3(10);
        return 0;
    }
    __int64 fib(int n){
        return (2>n) ? (__int64)n:fib(n - 1) + fib(n - 2);
    }
    __int64 fib2(long n, __int64 & prev){//第n项、prev:n-1项的值
        if (0 == n){//直接取值:fib(-1) = 1;fib(0) = 0;
            prev = 1;
            return 0;
        }
        else{
            __int64 prevPrev;
            prev = fib2(n - 1, prevPrev);
            return prevPrev + prev;
        }
    }
    
    __int64 fib3(int n){
        __int64  f = 0, g = 1;//初始化:fib(0) = 0,fib(1) = 1;
        while (0<n--)
        {
            g += f;
            f = g - f;
        }
        return f;
    }
    Fibonacci

    Mathematica  

    Fibonacci@Range[1, 33] // Select@EvenQ // Total

    简单粗暴!

     

     

    参考:  1.邓俊辉.数据结构(C++语言版).第三版.清华大学出版社.第一章

            2.hk

     

  • 相关阅读:
    新的思考方式
    我在干售后!
    设计制造嵌入式系统
    镶嵌在系统中的系统
    苏黄永郦的第六周读书报告
    苏黄永郦的第五周读书报告
    苏黄永郦的第四周读书报告
    苏黄永郦的第三周读书报告
    1051 最大子矩阵和
    1065 最小正子段和
  • 原文地址:https://www.cnblogs.com/dingblog/p/4500170.html
Copyright © 2020-2023  润新知