09求500万以内的亲合数

题目描述:求500万以内的亲合数

      

一:亲合数概念

       如果两个数a和b, a的所有真因子之和等于b,b的所有真因子之和等于a,则称a,b是一对亲和数。

       例如220和284:

220的真因子是:1、2、4、5、10、11、20、22、44、55、110;

284的真因子是:1、2、4、71、142。

       以sum[i]表示i的所有真因子之和,所以:

sum[220] = 1+2+4+5+10+11+20+22+44+55+110= 284

sum[284] =1+2+4+71+142 = 220

 

二:思路

       考虑用sum[i]表示i的所有真因子之和,所以sum为5000000大小的数组。所以该题的关键就是求解sum数组。

       如果考虑某个数i有哪些因子,则比较复杂,可以反过来考虑,对于i来说,哪些数是它的倍数?i的倍数有2*i, 3*i, ..., x*i。所有这些数的因子中都包含i。单纯用语言不好描述,直接看代码。

 

三:代码

#define MaxNum 5000000

 

         int*sum = NULL;

         inti, j;

         sum= malloc((MaxNum+10) * sizeof(int));

 

         //因为1是所有数的因子,所以,首先初始化sum数组的元素为1.

         for(i= 1; i <= MaxNum; i++)

         {

                  sum[i]= 1;

         }

 

         //i表示各个因子,从2开始,一直到(MaxNum/2)为止,因为MaxNum以内的数,不可能具有因子超过(MaxNum/2)的。对于数x,如果它具有因子y,则是x = dy,如果y != x,则最大因子y,是在d=2的时候取得的。

         for(i= 2; 2*i <= MaxNum; i++)

         {

                  // j表示所有i的倍数,因为i本身不能算作真因子,所以,

                  //2*i开始,一直到x*i <= MaxNum为止。

                  j= 2*i;     

                  while(j<= MaxNum)

                  {

                          sum[j]+= i;      //i加到相应的sum[j]上,因为ij的因子

                          j+= i;                 //j相应的由n*i,变为(n+1)*i

                  }

         }

 

         //开始扫描sum数组,求得亲合数

         for(i= 1; i <= MaxNum; i++)

         {

                  //这个条件是为了防止重复,比如出现了220 284,就不能再次出现284 220

                  //同时避免出现i=sum[i]这样的数,比如6,这样的数称为完全数,不是亲合数

                  if(i< sum[i])                     

                  {

                          if(sum[i]< MaxNum)      //这是为了防止数组越界,参考下面的判断条件

                          {

                                   if(sum[sum[i]]== i)

                                   {

                                            printf("%d%d\n", i, sum[i]);

                                   }

                          }

                  }

         }

 

(http://blog.csdn.net/v_JULY_v/article/details/6441279)

posted @ 2015-06-11 10:54  gqtc  阅读(217)  评论(0编辑  收藏  举报