亲和数是一种古老的数

题目:

    实现100000以内的相亲数对输出

    相亲数:除自身以外的约数和,比如:220:1+2+4+5+10+11+20+22+44+55+110=284,284:1+2+4+71+142=220,所以220和284构成相亲数对。

    输出格式:从小到大每行一对相亲数对,中间一个空格隔开。

    看到这个题目,第一个朴素的想法就是让计算机循环计算啊!事实证明,朴素的想法是最原始的,也是最慢的,10万以内还可以接受,100万以上就呵呵了!

算法一:慢的很

/*功能:求解相亲数
  说明:最朴素的解法,也是最耗时的
*/
#include <stdio.h>
#include <time.h>
/*
功能:求正整数n的因子和
参数:n(一个正整数)
返回:n的所有因子和(除自身外所有的约数)
*/
unsigned int factorsSum(unsigned int n)
{
    unsigned int i, sum=0;
    for(i=1; i<n; i++)
        if(n%i == 0)
            sum += i;
    return sum;
}

#define MAX_N 100000

int main(int argc, char *argv[])
{
    double startTime,endTime;//开始时间,结束时间
    unsigned int numberFactorsSum[MAX_N], i, j;

    startTime=(double)clock();

    // 求 1~(MAX_N-1) 之间每个数的真因数之和 
    for(i=1; i<MAX_N; i++)
        numberFactorsSum[i] = factorsSum(i);
     
    for(i=1; i<MAX_N; i++)
        for(j=i+1; j<MAX_N; j++)
            // 根据亲合数的定义dao,判定 i 和 j 是不是亲合数 
            if(numberFactorsSum[i] == j && numberFactorsSum[j] == i)
                printf("%d %d\n", i, j); 
    endTime=(double)clock();
    printf("Total Run Time:%f\n",endTime-startTime);//linux下返回的是纳秒,windows下是毫秒
    return 0;
}

 

算法二:这是已知网络上最快的算法

/*计算相亲数的快速算法
*/

#include <stdio.h>
#include <time.h>
#define MAX_TEST 100000

long nTable[MAX_TEST];//素数表
char nFlag[MAX_TEST];
//构造未标记用于降低内存使用

void printConsole()
{
    for(long i=2;i<MAX_TEST;i++)
    {
        if(nFlag[i]==0)
        {
            if(nTable[i]<MAX_TEST&&(nTable[nTable[i]+1]+1==i))
                printf("%ld\t%ld\n",i,nTable[i]+1);
            nFlag[nTable[i]+1]=1;
        }
    }
}

int main()
{
    long j=0;
    double startTime,endTime;
    startTime=(double)clock();
    for(long i=2;i<MAX_TEST;i++)
    {
        j=(i<<1);
        while(j<MAX_TEST)
        {
            nTable[j]+=i;
            j+=i;
        }
    }
    endTime=(double)clock();
    printConsole();
    printf("Total Run Time:%f\n",endTime-startTime);
    //printf("数值:%ld\n",nTable[220]);
    return 1;
}

算法三:这是网上使用C#的算法,还没有改造,有时间改造为c

/*
参考资料:https://www.cnblogs.com/devil0153/archive/2010/08/23/AmicablePair-And-PerfectNumber-SP2.html(使用本方法)
          https://www.cr173.com/html/6390_all.html(未采用)
简单说一下概念,相亲数是指两个正整数中,彼此的全部约数之和(本身除外)与另一方相等。举例来说:
220的全部约数(除掉本身)相加是:1+2+4+5+10+11+20+22+44+55+110=284
284的全部约数(除掉本身)相加的和是:1+2+4+71+142=220
所以220和284就是一对相亲数。

那什么是完全数呢?即它所有的真因子(即除了自身以外的约数)的和恰好等于它本身。例如:
第一个完全数是6,它有约数1、2、3、6,除去它本身6外,其余3个数相加,1+2+3=6
第二个完全数是28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28
*/
/// <summary>
/// 部分分解不求和的空间算法
/// </summary>
public class Algorithm6
{
    public List<int> primeList = new List<int>();
    public int[] firstFactorList;
    public int[] remainingList;
    public int[] resultList;
    public int GetNextFactor(int num)
    {
        var max = (int)Math.Sqrt(num);
        for (int i = 0; i < primeList.Count; i++)
        {
            var p = primeList[i];
            if (p > max) break;
            if (num % p == 0)
                return p;
        }
        primeList.Add(num);
        return num;
    }
    public int GetSum(int num)
    {
        var factor = firstFactorList[num] = GetNextFactor(num);
        if (factor == num)
        {
            remainingList[num] = 1;
            return 1;
        }
        else
        {
            remainingList[num] = num / firstFactorList[num];
            var r = remainingList[num];
            while (r % factor == 0)
                r = r / factor;
            return (resultList[remainingList[num]] + remainingList[num]) * factor + (resultList[r] + r) - num;
        }
    }
    public void Run(int limit)
    {
        firstFactorList = new int[limit];
        remainingList = new int[limit];
        resultList = new int[limit];
        int perfertCount = 0;
        int amicablePairCount = 0;
        for (var num = 2; num < limit; num++)
        {
            var result = resultList[num] = this.GetSum(num);
            if (result == num)
            {
                Console.WriteLine("{0}是完全数", num);
                perfertCount++;
            }
            else if (result < num && resultList[result] == num)
            {
                Console.WriteLine("{0}和{1}是一对相亲数", result, num);
                amicablePairCount++;
            }
        }
        Console.WriteLine("在{0}到{1}中至少有{2}个完全数和{3}对相亲数", 2, limit, perfertCount, amicablePairCount);
    }
}
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值