C++案例实战:破解完全数

扯一会儿

哈哈哈哈!我终于更了

事情是这样的——

春风得意马蹄疾,一日看尽长安花。这几天没有文案可写,又开学了,在书上面看见一个有趣的东西:

        完全数!

没错,做着数学题脑子又飞到编程上去了。。。

开始搞!

开始搞

        什么是完全数???

完全数就是它的所有因数(也称约数)除了它本身的和正好等于这个数,所有因数除了它本身也是连续的数。

比如:

6就是一个完全数。它的约数有1、2、3、6。去掉它的本身,剩下1、2、3,正好1 + 2 + 3 = 6,1、2、3也是连续的。

        题目要求

                题目

请输出2 ~ 1000000000000000000(即10^18)的完全数,并统计数量。

                样例输入

(无)

                样例输出

6
28
...
一共有...个完全数。

        代码思想:

                方法1:因数累加

                        这个比较好想:

#include <iostream>
using namespace std;

int s;
const long long MAX = 1e18;  // 设定一个合理的上限

int main(void)
{
    for(int i = 2; i <= MAX; i++)
    {
        int sum = 0;  // 在每次外层循环开始时重置sum
        
        // 找出所有真因数并累加
        for(int j = 1; j < i; j++)    // 注意这里是j < i而不是j <= i
        {
            if(i % j == 0)
                sum += j;
        }
    
        // 判断是否为完全数
        if(i == sum)
            cout << i << endl;
    }
    cout << "一共有" << s << "个完全数";
    return 0;
}

                但。。。。。。

                这可不是我想要的效果啊啊啊啊啊!w(゚Д゚)w

                太慢了。。。。。。有没有更快的方法呢?

                方法2:欧几里得 - 欧拉定理

#include <iostream>
#include <cmath>
using namespace std;

int s;

// 快速判断素数的函数(针对梅森数优化)
bool isPrime(long long num) {
    if (num <= 1) return false;
    if (num == 2) return true;
    if (num % 2 == 0) return false;
    
    // 对于梅森数,只需检查到sqrt(num)即可
    for (long long i = 3; i <= sqrt(num); i += 2) {
        if (num % i == 0) return false;
    }
    return true;
}

int main() {
    const long long MAX = 1e18;  // 设定一个合理的上限
    
    // 已知的梅森素数指数p(截至2023年发现51个)
    int knownPrimes[] = {2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127};
    
    for (int p : knownPrimes) {
        long long part1 = pow(2, p-1);
        long long part2 = pow(2, p) - 1;
        
        // 防止溢出
        if (part1 > MAX / part2) break;
        
        long long perfect = part1 * part2;
        
        if (perfect <= MAX) {
        	s++;
            cout << perfect << endl;
        }
    }
    cout << "一共有" << s << "个完全数";
    
    // 对于较小范围,也可以使用优化的暴力算法
    // 但这里仅展示数学方法
    return 0;
}

算法优化说明:

  1. 数学方法:利用欧几里得 - 欧拉定理,时间复杂度降为 O (k),其中 k 是已知梅森素数的数量。
  2. 素数判断优化:对于梅森数 2^p -1,使用试除法到平方根即可。
  3. 溢出处理:在计算前检查是否会溢出,确保程序安全运行。

注意事项:

  • 该算法只能找到与已知梅森素数对应的完全数。目前已知的梅森素数有 51 个,但非常大(最大的有超过 2400 万位)。
  • 对于普通计算机,输出超过前 12 个完全数(对应代码中的已知素数)会导致数值溢出或内存不足。
  • 如果需要寻找特定范围内的完全数,可以结合使用优化的暴力算法(例如只检查偶数并优化因数查找)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐星空Maker

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值