题目来源: HJ56 完全数计算
题目描述:
- 描述: 完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。
它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。
例如:28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。
输入n,请输出n以内(含n)完全数的个数。
数据范围: - 输入描述: 输入一个数字n
- 输出描述: 输出不超过n的完全数的个数
示例1:
输入:1000
输出:3
思路
反其道而行之,题目虽然求的是完全数,但是其实就是求一个数的所有约数,然后将除自身外的约数相加,结果等于自身,则为完全数。所以,题目的核心就是求一个数的所有约数。
具体实现:
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int Sum = 0;
for(int i = 1;i <= n;i++){
if(Perfect(i)){
Sum ++;
}
}
System.out.println(Sum);
}
static boolean Perfect(int number){ //判断是否满足完全数
int sum = 0;
for(int i = 1;i <= Math.sqrt(number);i++){
if(number % i == 0){ //求每个数的约数
if(number / i == i){ //如果除数和商相同,那么只保留一个作为约数,
//达到去重的效果
sum += i;
}else{ //如果除数和商不同,那么两个都保留作约数
sum += i;
sum += number/i;
}
}
}
//上述for循环,会将数的所有约数相加,但是其中包括自身
//所以要将自身从求得的总数中减去
if(sum-number == number){
return true;
}else{
return false;
}
}
}
思路杂记
1.我们这道题的思路,其实就是用N除1到N的二次平方根,余数为0时,取除数及整除的结果,但是为什么除到二次平方根就可以了呢?
如果有非平方数N=a×b,其中a<b,那么一定有a<,b>,对于每一个小于的N的约数a,都有一个对应的b>,b也是N的约数,因此我们只需要遍历2到就可以了,每一次整除都对应了N的两个约数,最后只需要再考虑一下N是不是平方数就可以了。这样,时间复杂度就被优化到了
- 最后考虑N是不是平方数,是为了
if(number / i == i){ //如果除数和商相同,那么只保留一个作为约数 sum += i; }
2.对于求一个数的约数,其实有很多种思路
- 思路1:给定的数N依次除以1到N的数,余数为0则是约数
static boolean Perfect(int number){
int sum = 0;
for(int i = 1;i <= number;i++){
if(number % i == 0){
sum += i;
}
}
if(sum-number == number){
return true;
}else{
return false;
}
}
- 思路2:对于一个数N,存在N/N==1,而N与1分别是数N的最大约数与最小约数,同理,次大约数就是N/2
我们可以进一步减少循环的次数,N除以1到N/2, 余数为0为是约数
static boolean Perfect(int number){
int sum = 0;
for(int i = 1;i <= number/2;i++){
if(number % i == 0){
sum += i;
}
}
if(sum == number){ //因为sum是从1加到次大约数,并没有+最大约数(数自身),所以无需减去自身
return true;
}else{
return false;
}
}