那天的题挺简单的
下面来看下
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