题目
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
https://projecteuler.net/problem=5
分析
可以将题目理解为求1-20的最小公倍数,即设计一个求多个数的最小公倍数函数。我将函数原型设为:__int64 Arr_Lcm(vector<int> v);
解法1(公倍数法):利用求两个最小公倍数方法:int Lcm(int a, int b);先求出其中两个数的最小公倍数,再求这个最小公倍数与第三个数的最小公倍数,依次求解
解法2(素数法):可以观察到:LCM(1~10)= 2 ^ 3 * 3 ^ 2 * 5 ^ 1 * 7 ^ 1 = 2520
“1.列出20以内的质数,并求这些质数的小于20的最高次幂
2.再将这些质数的最高次幂的积相乘”
ps:这个方法也是PE官网Download overview给出的方法,分析写了好长(看了半天没看懂),
后来结果看到@cfeibiao博客的这句话,秒懂了,就不贴这个方法的代码了,可以参考他博客中Python的实现。
Code
Lcm利用了求最大公约数(Gcd)的方法,和结论(两数之积 = Lcm*Gcd)此外还要注意返回时要用大于__int64,使用int,会发生了上溢,得到错误结果;
代码部分,顺便把Arr_Gcd的方法也写了,把最大公约数,最小公倍数 的方法给总结了。
#include <iostream> #include <vector> using namespace std; int Lcm(int a, int b); __int64 Arr_Lcm(vector<int> v); int Gcd(int a, int b); int Arr_Gcd(vector<int> v); int main(){ vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; __int64 r = Arr_Lcm(v); cout << r; return 0; } int Gcd(int a, int b){ if (a < b)swap(a, b); while (b != 0) { int tmp = a % b; a = b; b = tmp; } return a; } int Lcm(int a, int b){ int f = Gcd(a, b); return (__int64)a*b / Gcd(a, b); } __int64 Arr_Lcm(vector<int> v){ __int64 a = v[0]; __int64 b; for (int i = 1; i < v.size(); i++) { if (i == 18){ int f = 1; } int tt = v[i]; b = Lcm(a, v[i]); a = b; } return a; } int Arr_Gcd(vector<int> v){ int a = v[0]; int b; for (int i = 0; i < v.size(); i++) { b = Gcd(a, v[i]); a = b; } return a; }
Mathematica
LCM @@ Range[1, 20]
by the way C++的vector好像没有vector初始化为递增序列的,利用Mma、Range[1,20]粘贴复制真是爽,除此之外还可以做各种验证、计算来辅助分析!
用vs断点增删代码来测试数据,点F5实在麻烦。
Mma简直就是个超级计算器,没用过的同学,上面一行简洁的代码有没有打动你~~....!。
参考:cfeibiao