东方博宜OJ 1136:输出m和n范围内的完全数(完美数) ← 约数的成对性

【题目来源】
https://oj.czos.cn/p/1136

【题目描述】
任何一个自然数的约数中都有1和它本身,我们把小于它本身的因数叫做这个自然数的真约数。 如6的所有真约数是 1、2、3,而且 6=1+2+3。
像这样,一个数所有真约数的和正好等于这个数,通常把这个数叫做完美数。 古希腊人非常重视完美数。毕达哥拉斯发现它之后,人们就开始了对完美数的研究。
现在要求输出所有在 m 和 n 范围内的完美数。

【输入格式】
输入只有一行,是两个整数 m,n,中间用空格隔开。(2≤m≤n≤32767)

【输出格式】
输出范围内的所有完全数,数与数之间用空格隔开。

【输入样例】
2 10

【输出样例】
6

【数据范围】
2≤m≤n≤32767

【算法分析】
● 下面算法的时间复杂度为 O(mn),当 n 较大(如大于 10^4 或 10^5)时,算法超时(TLE)。

#include <bits/stdc++.h>
using namespace std;

bool f(int x) {
    int sum=0;
    for(int i=1; i<x; i++) {
        if(x%i==0) sum+=i;
    }
    if(sum==x) return true;
    else return false;
}

int main() {
    int m,n;
    cin>>m>>n;
    for(int i=m; i<=n; i++) {
        if(f(i)) cout<<i<<" ";
    }

    return 0;
}

/*
in:2 10
out:6
*/

● 约数的成对性‌:对于任意整数 x,如果 i 是 x 的约数,那么 x/i 也是 x 的约数。
这意味着,如果 i×j=x,那么在这对约数 (i,j) 中,必然有一个小于或等于 sqrt(x)。另一个大于或等于 sqrt(x)。只有当 x 是完全平方数时,两者相等。

【算法代码】
基于“约数的成对性”进行优化。另外,由于 1 肯定是约数,所以据题意,先加到 sum 中。

#include <bits/stdc++.h>
using namespace std;

bool f(int x) {
    if(x<=1) return false;
    int sum=1;
    for(int i=2; i*i<=x; i++) {
        if(x%i==0) {
            sum+=i;
            if(i!=x/i) sum+=x/i;
        }
    }
    return sum==x;
}

int main() {
    int m,n;
    cin>>m>>n;
    for(int i=m; i<=n; i++) {
        if(f(i)) cout<<i<<" ";
    }

    return 0;
}

/*
in:2 10
out:6
*/



【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/161995534

  

posted @ 2026-06-15 14:56  Triwa  阅读(4)  评论(0)    收藏  举报