题目的主要信息:
- 完全数所有的真因子(即除了自身以外的约数,包括1)的和,恰好等于它本身
- 请输出n以内的完全数的个数
方法一:枚举
具体做法:
我们可以枚举1到n的每个数字,判断其是否是完全数,如果是则计数,否则跳过。
判断的时候我们从1遍历到找每个数的因子,如果是因子我们将这个因子和这个因子对应的另一个相加,当然要判断因子是否是的开方,如果刚好是开方就只加一次。然后减去这个数本身,因为因子为1时另一个因子为这个数,累加和加上了这个因子本身,最后检查这个累加和与这个数是否相等,相等则是完全数,不相等则不是。
#include<iostream>
#include<algorithm>
using namespace std;
bool isPefect(int n){ //判断数字n是否是完全数
    int sum = 0;
    for(int i = 1; i * i <= n; i++){ //遍历从1到根号n
        if(n % i == 0){ //如果是因子
            if(i * i == n){ //先判断是否是开方,开方只有1个因子
                sum += i; 
                break;
            }
            else //其他情况都有两个因子
                sum += i + n / i;
        }
    }
    sum -= n; //减去本身
    return sum == n ? true : false; //判断和是否等于本身
}
int main(){
    int n;
    while(cin >> n){
        int count = 0;
        for(int i = 1; i <= n; i++){ //枚举数字1到n
            if(isPefect(i)){ 
                count++;
            }
        }
        cout << count << endl;
    }
    return 0;
}
复杂度分析:
- 时间复杂度:,遍历1到n,每个数检查从1到
- 空间复杂度:,无额外空间
方法二:打表
具体做法:
从方法一的答案中我们发现,完全数的个数是非常少的,范围内就只有6,28,496,8192四个,而下一个完全数已经达33550336,超出输入范围。因此我们可以判断输入的n在上面哪个范围之内,根据范围输出相应的完全数个数。
#include<iostream>
using namespace std;
int main(){
    int n;
    while(cin >> n){
        //根据n所属区间输出
        if(n < 6)
            cout << 0 << endl;
        else if(n < 28)
            cout << 1 << endl;
        else if(n < 496)
            cout << 2 << endl;
        else if(n < 8192)
            cout << 3 << endl;
        else
            cout << 4 << endl;
    }
    return 0;
}
复杂度分析:
- 时间复杂度:,直接判断,常数时间
- 空间复杂度:,无额外空间

 京公网安备 11010502036488号
京公网安备 11010502036488号