解题思路
-
完全数的定义:一个数等于它的所有真因子(除了自身以外的约数)之和
- 例如:28的真因子有1,2,4,7,14,且1+2+4+7+14=28
-
实现思路:
- 遍历1到
的每个数
- 对每个数找出其所有真因子
- 判断真因子之和是否等于该数本身
- 统计满足条件的数的个数
- 遍历1到
-
优化:
- 只需要遍历到
就可以找到所有因子
- 已知的完全数很少,可以直接判断
- 只需要遍历到
代码
#include <iostream>
using namespace std;
bool isPerfectNumber(int num) {
if (num <= 1) return false;
int sum = 1; // 1总是因子
// 只需要遍历到sqrt(num)
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
sum += i;
if (i * i != num) { // 避免平方数重复计算
sum += num / i;
}
}
}
return sum == num;
}
int main() {
int n;
while (cin >> n) {
int count = 0;
for (int i = 1; i <= n; i++) {
if (isPerfectNumber(i)) {
count++;
}
}
cout << count << endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
private static boolean isPerfectNumber(int num) {
if (num <= 1) return false;
int sum = 1; // 1总是因子
// 只需要遍历到sqrt(num)
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
sum += i;
if (i * i != num) { // 避免平方数重复计算
sum += num / i;
}
}
}
return sum == num;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int count = 0;
for (int i = 1; i <= n; i++) {
if (isPerfectNumber(i)) {
count++;
}
}
System.out.println(count);
}
}
}
def is_perfect_number(num):
if num <= 1:
return False
sum_factors = 1 # 1总是因子
# 只需要遍历到sqrt(num)
i = 2
while i * i <= num:
if num % i == 0:
sum_factors += i
if i * i != num: # 避免平方数重复计算
sum_factors += num // i
i += 1
return sum_factors == num
while True:
try:
n = int(input())
count = 0
for i in range(1, n + 1):
if is_perfect_number(i):
count += 1
print(count)
except EOFError:
break
算法及复杂度
- 算法:试除法找因子
- 时间复杂度:
- 需要遍历1到n的每个数,每个数需要
的时间找因子
- 空间复杂度:
- 只使用了常数额外空间