所谓亲和数对,是指两个不同的自然数,其中任何一个数的真因数之和都恰好等于另一个数。例如:220 和 284 就是一对亲和数对。
220 的全部真因数包括:1、2、4、5、10、11、20、22、44、55、110, 它们的和恰为 284;
284 的全部真因数包括:1、2、4、71、142,它们的和也恰好为 220。
据说,两个好朋友佩带写有亲和数对的护身符可使两人保持良好的友谊。
请编写程序,输入区间的下限和上限,若该区间内存在亲和数对,则输出区间内的全部亲和数对,否则输出 None。
输入格式:
两个正整数 a 和 b,且 a ≤ b ≤ 100000000,即区间 [a, b] 的下限和上限
输出格式:
若存在亲和数对,则输出若干行,每行一个亲和数对,均在区间 [a, b] 内,且前者小于后者,两者以空格间隔;否则输出 None。
输入样例1
1000 3000
输出样例1
1184 1210
2620 2924
输入样例2
7000 9000
输出样例2
None
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
此代码为csnd上以一位大佬写的c++的改编成c语言的,并非完全原创!!
#include<stdio.h>
int sum[5000010]; //为防越界
int main()
{
int i, j,a,b,count=0;
scanf("%d%d",&a,&b);
for (i = 0; i <= 5000000; i++)
sum[i] = 1; //1是所有数的真因数所以全部置1
for (i = 2; i + i <= 5000000; 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))。
{
//5000000以下最大的真因数是不超过它的一半的
j = i + i; //因为真因数,所以不能算本身,所以从它的2倍开始
while (j <= 5000000)
{
//将所有i的倍数的位置上加i
sum[j] += i;
j += i;
}
}
for (i =a; i <=b; i++) //扫描,O(N)。
{
// 一次遍历,因为知道最小是220和284因此从220开始
if (sum[i] > i && sum[i] <= 5000000 && sum[sum[i]] == i)
{
//去重,不越界,满足亲和
printf("%d %d\n",i,sum[i]);
count++;
}
}
if(count==0)
printf("None");
return 0;
}