欧拉计划(1~3)ps:以后看题一定要认真

那天的题挺简单的

下面来看下

  No1

  If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

  Find the sum of all the multiples of 3 or 5 below 1000.

//project euler num1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{                                                      
    int sum = 0;
    int i;
    for(i = 0; i < 1000; i++)
    {   
        if(i % 3 == 0 || i % 5 == 0)
            sum += i;
    }   

    printf("The sum is %d\n", sum);
}

  第一题很简单,不解释~

  No 2 

  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

  第二题是求斐波那契数列小于 4e6 的那些偶数项的和,很简单的想到了递归算法

  

//project euler pro02
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int fib_temp[10000];//避免重复运算,算好的项存入数组

int fib(int n)
{
    if(n == 1)                                                                                       
    {
        fib_temp[0] = 1;
        return fib_temp[0];
    }
    else if( n == 0)
    {
        fib_temp[1] = 2;
        return fib_temp[1];
    }
    else
    {
        if(fib_temp[n - 1] != 0)
        {                                                                                         
            if(fib_temp[n - 2] != 0)
                 return fib_temp[n - 1] + fib_temp[n - 2];//如果已经预存,直接返回
            else
                fib_temp[n - 2] = fib( n - 2);
                return fib_temp[n - 1] + fib_temp[n - 2];
        }
        else
        {
            fib_temp[n - 1] = fib(n - 1);
            fib_temp[n - 2] = fib(n - 2);
            return fib_temp[n - 1] + fib_temp[n - 2];
        }
    }
}

int sum_even_fib(int top_num)
{

    int i = 0;
    int sum = 0;
    int temp = 0;
    while(1)
    {
        if(i % 2 == 0)
        {
            if((temp = fib(i)) < top_num)
                sum += temp;
            else
                break;
        }
        i++;
    }
    return sum;
}

int main()
{

    int sum = sum_even_fib(400000000);
    cout << sum << endl;
    return 0;
}             
                

  就是这样,没有选用最基本的递归方法是因为效率过低,不如把算好的想先存入数组,避免重复计算。

  但是这让我想起了之前的动态规划算法:

  递归算法是很简单的自顶向下,从上可以看出是从n一步步的计算到第一项;

  但是动态规划恰恰相反,它是先从第一项开始计算,然后把算好的结果存入数组以备后用。

  //project euler pro02                                                                                            
   #include <iostream>
   #include <string>
   #include <vector>
   using namespace std;
   
   int fib_temp[10000];
   //設立預存數組
   int fib(int n)
  {
      if( n == 0 || n == 1)
      {
          if(fib_temp[0] == 0)
              fib_temp[0] = 1;
          if(fib_temp[1] == 0)
              fib_temp[1] = 2;
          //對前兩項初始化
      }
      else
      {
          for(int i = 2; i <= n; i++)
          {
              if(fib_temp[i] == 0)
                  fib_temp[i] = fib_temp[i - 1] + fib_temp[i - 2];
              //用循環計算後面的項
          }
      }
      return fib_temp[n];
      //直接返回數組中的項
  }
  
 int sum_even_fib(int top_num)
 {
      int i = 0;
      int sum = 0;
      int temp = 0;
      while(1)
      {
          if((temp = fib(i)) % 2 == 0)
          {
              if(temp < top_num)
                  sum += temp;
              else
                  break;
          }
          cout << fib(i) << endl;
          i++;
      }
      return sum;     
 }
  int main()
  {
      int sum = sum_even_fib(4e6);
      cout << sum << endl;
      return 0;
  }                                                  
          

  No3

  The prime factors of 13195 are 5, 7, 13 and 29.

  What is the largest prime factor of the number 600851475143 ?

  我会说就是这个我没有看清楚题么,我看做是求小于这个数的所有素数~

  但是题目是求小于这个数的最大素因子。

  悲伤~~

  好吧,两个都做完了,先看计算最大素因子。

   #include <iostream>                                                                              
   #include <string>
   #include <vector>
   #include <math.h>
   
   using namespace std;
   
   
   bool is_prime(long long int i)
  {
      long long int j;                                                                           
      for(j = 2; j <= sqrt(i); j ++)
      {    
          if(i % j == 0)
              return false;
      }
      if(j > sqrt(i))
          return true;
  }
  //这是判断素数的
  
  void max_prime_facter(long long int n)
  {
      if(is_prime(n))
      {
          cout << n << endl;
          return;
          //如果n本身就是素数,直接输出
      }
      for(long long int i = 2; i < (n / 2); ++i)
      {
          if(n % i == 0)
          {
              n = n / i;
              //如果找到一个小的因子,替换n为n/i
              cout << "factor is " << i << endl;
              i = 2;
              //重置循环变量
              if(is_prime(n))
              {   
                  cout << n << endl;
                  //如果在过程中发现n变为了素数,说明
    得到了最大的素因子
                  break;
              }
          }
      }
  }
  
  int main(int argc, const char *argv[])
  {
      long long int n = 600851475143;
      max_prime_facter(n);
      return 0;
  }                                      
                           

  看~不难吧。

  那么问题就来了, 挖掘机到底那家强!!

  小扯一下,那么如果我想输出小于这个数的所有素数呢?

  先说一下这个程序的基本思想:

  传统的输出小于这个数的所有素数就是, 

  一个循环,依次判断,但是判断素数是一个很繁琐的事情。

  所以我们就想可不可以把一些数省掉呢?

  首先所有偶数都是合数。

  那么自然而然的就想到了算数基本定理:所有合数都可以表示为素因子的乘积。

   #include <iostream>
   #include <string>
   #include <vector>                                  
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   #include <math.h>
   using namespace std;
   
  bool is_prime(long long int i)
  {
      for(long long int j = 2; j <= sqrt(i); j ++)
      {
          if(i % j == 0)
              return false;
      }
      if(i > sqrt(i))
          return true;
  }
  //判断素数的函数
  vector<int> vec_prime;
  //一个存放素数的数组
  void  prime_number(long long int n)
  {
      long long int max;
      for (int i = 2; i < n; i++) 
      {
          if(vec_prime.size() != 0)
          //一开始数组内是没有元素的
          {
              vector<int>::iterator it ;
              for( it = vec_prime.begin(); it != vec_    prime.end(); ++it)
              {
                  if(i % (*it) == 0) 
                     break;
                  //依次判断数组内有没有其的因子
              }
             if(it != vec_prime.end()) 
                 continue;       
             //这表示有他的素因子
          }
          if(is_prime(i) == true)
          //到这里说明数组中没有这个数的因子
          //因为我们知道一切正整数都可以表示成素数的乘积
          //反之,如果这个数不能表示成素数的乘积
          //那么这个数本身很可能就是素数
          //所以判断他是否是素数,是的话就加入数组
          {
              vec_prime.push_back(i);
              cout << i << endl;
              //依次输出素数
          }
      } 
      return ;
  }
  
  int main()           
  {
  
      long long int n = 600851475143;
      prime_number(n);
      return 0;
  }                                                         

  可以看到这个算法其实是非常快速的~

 

  补充:

    今早起来突然想到上面的程序是不是还不够快呢~

    可不可以把判断素数的函数省掉呢?

    事实上,判断素数就是多余的。

    因为所有正整数都可以表示为它一组素因子的乘积或者是它本身与 1 的乘积。

 1 #include <iostream>                                
  2 #include <string>
  3 #include <vector>
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <math.h>
  8 using namespace std;
  9 
 10 bool is_prime(long long int i)
 11 {
 12     for(long long int j = 2; j <= sqrt(i); j ++)
 13     {
 14         if(i % j == 0)
 15             return false;
 16     }
 17     if(i > sqrt(i))
 18         return true;
 19 }
 20 //判断素数的函数
 21 vector<int> vec_prime;
 22 //存入第一个素数
 23 //一个存放素数的数组
 24 void  prime_number(long long int n)
 25 {
 26 
 27     if(vec_prime.size() == 0)
 28         vec_prime.push_back(2);
 29 
 30     long long int max;
 31     for (int i = 3; i < n; i += 2)
 32     {
 33         //一开始数组内是没有元素的
 34             vector<int>::iterator it ;
 35             for( it = vec_prime.begin(); it != vec_prime.end(); ++it)
 36             {
 37                 if(i % (*it) == 0) 
 38                    break;
 39                 //依次判断数组内有没有其的因子
 40             }
 41            if(it != vec_prime.end())      
 42                continue;
 43            else if(it == vec_prime.end())
 44            {
 45                 vec_prime.push_back(i);
 46                 cout << i << endl;
 47            }
 48            //这表示有他的素因子
 49         //到这里说明数组中没有这个数的因子
 50         //因为我们知道一切正整数都可以表示成素数的乘积
 51         //反之,如果这个数不能表示成素数的乘积
 52         //那么这个数本身很可能就是素数
 53         //所以判断他是否是素数,是的话就加入数组
 54             //依次输出素数
 55     } 
 56     return ;
 57 }
 58 
 59 int main()
 60 {
 61 
 62     long long int n = 600851475143;
 63     prime_number(n);
 64     return 0;
 65 }                       

    实验一下发现这个程序还是非常快速的。

    那么我们就得到了这样的程序:

  

 

  最后再说一下:

  今天学习了c++中的两个新的数据类型long long int 和 _int64.

  参考文章:

  http://www.cnblogs.com/jiai/articles/2613900.html

  http://www.cnblogs.com/felove2013/articles/3880590.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值