第四章、亲和数问题--求解500万以内的亲和数
来源:互联网 发布:stm32是单片机还是arm 编辑:程序博客网 时间:2024/04/30 05:57
第一节、亲和数问题
题目描述:求500万以内的所有亲和数
题目描述:求500万以内的所有亲和数
如果两个数a和b,a的所有真因数之和等于b,b的所有真因数之和等于a,则称a,b是一对亲和数。例如220和284,1184和1210,2620和2924。
分析:
首先得明确到底是什么是亲和数?
亲和数问题最早是由毕达哥拉斯学派发现和研究的。他们在研究数字的规律的时候发现有以下性质特点的两个数:
220的真因子是:1、2、4、5、10、11、20、22、44、55、110;
284的真因子是:1、2、4、71、142。
而这两个数恰恰等于对方的真因子各自加起来的和(sum[i]表示数i 的各个真因子的和),即
220=1+2+4+71+142=sum[284],
284=1+2+4+5+10+11+20+22+44+55+110=sum[220]。
得284的真因子之和sum[284]=220,且220的真因子之和sum[220]=284,即有sum[220]=sum[sum[284]]=284。
第二节、程序的构造与解释
我再来具体解释下上述程序的原理,举个例子,假设是求10以内的亲和数,求解步骤如下:因为所有数的真因数都包含1,所以,先在各个数的下方全部置1
- 然后取i=2,3,4,5(i<=10/2),j依次对应的位置为j=(4、6、8、10),(6、9),(8),(10)各数所对应的位置。
- 依据j所找到的位置,在j所指的各个数的下面加上各个真因子i(i=2、3、4、5)。
整个过程,即如下图所示(如sum[6]=1+2+3=6,sum[10]=1+2+5=8.):
1 2 3 4 5 6 7 8 9 10
1 1 1 1 1 1 1 1 1 1
2 2 2 2
3 3
4
5 - 然后一次遍历i从220开始到5000000,i每遍历一个数后,
将i对应的数下面的各个真因子加起来得到一个和sum[i],如果这个和sum[i]==某个i’,且sum[i‘]=i,
那么这两个数i和i’,即为一对亲和数。 - i=2;sum[4]+=2,sum[6]+=2,sum[8]+=2,sum[10]+=2,sum[12]+=2...
i=3,sum[6]+=3,sum[9]+=3...
...... - i=220时,sum[220]=284,i=284时,sum[284]=220;即sum[220]=sum[sum[284]]=284,
得出220与284是一对亲和数。所以,最终输出220、284,...
代码如下:#include<iostream>#define SIZE 50000using namespace std;int main() { int i, j;int *sum = new int[SIZE + 10];for (i = 0; i <=SIZE ; i++) sum[i] = 1; //1是所有数的真因数所以全部置1for (i = 2; i + i <= SIZE; i++)//预处理,预处理是logN(调和级数)*N。调和级数1/2 + 1/3 + 1/4......的和近似为ln(n),//因此O(n *(1/2 + 1/3 + 1/4......)) = O(n * ln(n)) = O(N*log(N))。{ j = i + i; //因为真因数,所以不能算本身,所以从它的2倍开始 while (j <= SIZE) { //将所有i的倍数的位置上加i sum[j] += i; j += i; } }for (i = 220; i <= SIZE; i++) //扫描,O(N)。{// 一次遍历,因为知道最小是220和284因此从220开始 if (sum[i] > i && sum[i] <= SIZE && sum[sum[i]] == i){//去重,不越界,满足亲和cout << i << " " << sum[i] << endl; } }delete []sum;return 0;}
代码如下:
#include<stdio.h>#define SIZE 100int main() { int i, j;int *sum = new int[SIZE + 10];for (i = 0; i <= SIZE; i++) sum[i] = 1; for (i = 2; i + i <= SIZE; i++) //预处理,预处理是logN(调和级数)*N。//@litaoye:调和级数1/2 + 1/3 + 1/4......的和近似为ln(n),//因此O(n *(1/2 + 1/3 + 1/4......)) = O(n * ln(n)) = O(N*log(N))。{ j = i + i; //因为真因数,所以不能算本身,所以从它的2倍开始 while (j <= SIZE) { sum[j] = 0; j += i; } }for (i = 2; i <= SIZE; i++) //扫描,O(N)。{if(sum[i] != 0){printf("%d\n",i);} }delete []sum;return 0;}
- 第四章、亲和数问题--求解500万以内的亲和数
- 求解500万以内的亲和数
- 求解500万以内的亲和数
- 亲和数问题--求解500万以内的亲和数之—Scheme语言实现
- 第六章:求解500万以内的亲和数
- 006--求解500万以内的亲和数
- 寻找500万以内的亲和数
- 500万以内的亲和数
- 程序员编程艺术:第六章、求解500万以内的亲和数
- 程序员编程艺术:第六章、求解500万以内的亲和数
- 程序员编程艺术:第六章、求解500万以内的亲和数
- 程序员编程艺术:第六章、求解500万以内的亲和数
- 【程序员编程艺术】第六章:求解500万以内的亲和数
- 算法学习(五)求解500万以内的亲和数,连续数据映射为数组
- 如何求500万以内的所有亲和数
- 求500万以内的所有亲和数
- 亲和数问题求解
- 求5000000以内的亲和数
- Java多线程编程总结
- Android---Gallery
- Infragistics
- 自动挂载NFS目录的两个办法[技术]
- 汇编源码学习9-子程序设计-输入、输出大整数
- 第四章、亲和数问题--求解500万以内的亲和数
- Metasploit Framework命令汇总
- jacob将WORD转换成PDF文件(要装有Word另存为PDF文件的插件)
- android 退出程序 个人解决方法
- partial关键字的作用[C#]
- svn 版本冲突
- SQL with(nolock)详解
- hibernate 学习六——get(),load()
- 汇编源码学习10-子程序调用-高精度整数加法