zoukankan      html  css  js  c++  java
  • 亲和数问题

    求500万以内的亲和数                                                                                                                               

    “朋友是你灵魂的倩影,要像220与284一样亲密。”

    ——毕达哥拉斯

      首先需要知道什么事亲和数?亲和数是指,两个数a和b,如果a的所有真因子之和等于b,而b所有的真因子之和也等于a,那么着两个数被称为亲和数(真因子包括1,但不包括自身)。

      Example:

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

      284的真因子: 1, 2, 4, 71, 142

      284 = 1+2+4+5+10+11+20+22+44+55+110(220的真因子之和)

      220 = 1+2+4+71+142(284的真因子之和)

      解决方案:首先想到的办法,即穷举法:对于任意的两个数a和b,判断a和b是否能满足亲和数的条件。算法的时间复杂度O(N3),在数量级很大的情况下,算法的效率就显得非常低下。在穷举的时候可以做一些剪枝:从小数开始遍历,当前数a,求出其真因子之和b,然后在判断b对应的真因子之和是否等于a。然而这些类似处理办法,仅是“细节”上的优化,大方向“算法框架”不变,时间的复杂度也不会有多大的变化。

      那么,如何选择优化的方向呢?判断两个数是否互为亲和数,必须要求出他们的真因子,当数量级较大时,算法的耗时体现在求这些数的真因子上。一种解决该问题的方法是,从低向上,以空间换时间(类似与动态规划算的基本思想)构建解空间:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 int main()
     6 {
     7     const int love_size = 5000000;
     8     int *love_sum_array = new int[love_size];
     9     for (int i = 1; i < love_size; i++)       //1是所有数的真因子
    10     {
    11         love_sum_array[i] = 1;
    12     }
    13 
    14     for (int i = 2; i + i < love_size; i++)   //从2开始作为真因子项,为包含真因子项的love_sum加上该真因子项         
    15     {
    16         int j = i + i;                        //自身不作为真因子项,从2倍的项开始
    17         while (j < love_size)
    18         {
    19             love_sum_array[j] += i;
    20             j += i;
    21         }
    22     }
    23 
    24     for (int i = 220; i < love_size; i++)
    25     {
    26         //越界与亲和数判断
    27         if (love_sum_array[i] < love_size && love_sum_array[love_sum_array[i]] == i)
    28         {
    29             cout<<i<<" "<<love_sum_array[i]<<endl;
    30         }
    31     }
    32 
    33     delete[] love_sum_array;
    34     system("pause");
    35     return 0;
    36 }

      程序的运行结果如下:

      

      上面的代码涉及的一个C/C++简单知识点:C/C++程序默认的栈内存大小是1M(约等于106)字节,而我们程序需要的内存空间4*06字节。因此,如果在程序中开辟内存:int love_sum_array[love_size],程序会报栈内存溢出错误,而采用堆的内存申请方式:int *love_sum_array = new int[love_size],则不会有这样的限制。

      

  • 相关阅读:
    多线程系列教材 (四)- 常见的线程安全相关的面试题
    多线程系列教材 (三)- Java 多线程同步 synchronized 详解
    多线程系列教材 (二)- Java 常见的线程方法
    UPC-最优分解问题(贪心)
    【数论】【模板】
    UPC-人品指数(模拟)
    UPC-趾压板矩阵(强行找规律)
    UPC-排队出发+AcWing-耍杂技的牛(推公式的贪心)
    UPC-购买巧克力(贪心)
    前端——多行三列模式页面布局
  • 原文地址:https://www.cnblogs.com/wangbogong/p/3240616.html
Copyright © 2011-2022 走看看