首页 > 代码库 > 算法进化历程之相亲数

算法进化历程之相亲数

算法进化历程之相亲数

巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo


题目来自于编程论坛“吴健飞飞”的提问:求4位数以内的相亲数对

     2500年前数学大师毕达哥拉斯发现,220与284两数之间存在下列奇妙的联系:
220的真因数之和为1+2+4+5+10+11+20+22+44+55+110=284
284的真因数之和为1+2+4+71+142=220

毕达哥拉斯把这样的数对a,b称为相亲数:a的真因数(小于本身的因数)之和为b,而b的真因数之和为a。

版主rjsp给出了两个精妙的算法,我对其进行了整理,作出此文。对为此文提供灵感的网友表示感谢。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

void AmicablePair_1(int n);//求相亲数的原始方法 
void AmicablePair_2(int n);//以空间换时间
void AmicablePair_3(int n);//用加法运算代替求余运算,更加高效 
  
int main(void)
{
    unsigned n = 1000000;

    clock_t begin, end;
    double  cost;
    begin = clock();
    
	AmicablePair_1(n);//求相亲数的原始方法 
	
    end = clock();
    cost = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("%lf seconds\n", cost);

    begin = clock();
    
	AmicablePair_2(n);//求相亲数的原始方法 
	
    end = clock();
    cost = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("%lf seconds\n", cost);
    
    begin = clock();
    
	AmicablePair_3(n);//求相亲数的原始方法 
	
    end = clock();
    cost = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("%lf seconds\n", cost);
    
    return 0;
}

void AmicablePair_1(int n)//求相亲数的原始方法 
{
	unsigned i, j, sa, sb;
	
	for (i=2; i<=n; i++)
    {
        sa = 1;
        for (j=sqrt(i); j>1; j--)//计算i的真因数和 
        {
            if (i % j == 0)
                sa += j + i / j;
        }
        if (sa <= i)//确sa>i,以避免重复计算 
            continue;
        sb = 1;
        for (j=sqrt(sa); j>1 && sb<=i; j--)//计算sa的真因数和 
        {
            if (sa % j == 0)
                sb += j + sa / j;
        }
        if (sb == i)
            printf( "%u\t%u\n", i, sa);
    }
}

void AmicablePair_2(int n)//以空间换时间
{
	unsigned i, j;
	int *p = (unsigned*)malloc(sizeof(unsigned)*(n+1));
	
	if( !p )
    {
		printf("Out of space!");
		exit(0);
	}
	
	for (i=2; i<=n; i++)
    {
        p[i] = 1;
        for (j=sqrt(i); j>1; j--)//计算i的真因数和,并存储在p[i]中 
        {
            if (i % j == 0)
                p[i] += j + i / j;
            if (p[i] > n)
            {
                p[i] = 0;
                break;
            }
        }
    }
    
    for (i=2; i<=n; i++)
    {
        if (p[p[i]] == i && i < p[i]) //相亲数对 
            printf( "%u\t%u\n", i, p[i]);
    }
    
    free(p);
} 

void AmicablePair_3(int n)//用加法运算代替求余运算,更加高效 
{
	unsigned i, j, mid;
	int *p = (unsigned*)malloc(sizeof(unsigned)*(n+1));
	
	if( !p )
    {
		printf("Out of space!");
		exit(0);
	}
	
	mid = n / 2;
    for (i=1; i<=mid; i++)
    {
        for (j=i*2; j<=n; j+=i)//因为j是i的倍数,故i之和即j的真因数和
        {
            p[j] += i;
        }
    }
    
    for (i=2; i<n; i++)
    {
        if (p[i] <= n && p[p[i]] == i && i < p[i]) //相亲数对 
            printf( "%u\t%u\n", i, p[i]);
    }
    
    free(p);
} 



算法进化历程之相亲数