【C++】2029:【例4.15】水仙花数



博客主页:[小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C++


文章目录



💯前言

  • 在程序设计中,"水仙花数"是一个带有数学特色的热点题目。这个题目最核心的思路在于如何分解三位数,并检查它是否满足水仙花数的定义。通过进一步分析、优化,我们不仅能学习到原理,还可以探索于实现与效率之间的平衡点。本文将从题目解读、我的实现、老师做法、思路对比与优化,以及指向临水仙花数更学机。
    C++ 参考手册

💯题目描述

2029:【例4.15】水仙花数

题目要求如下:

  • 计算 100 到 999 中的水仙花数
    如果三位数 ( ABC ) 满足以下条件:
    A B C = A 3 + B 3 + C 3 ABC = A^3 + B^3 + C^3 ABC=A3+B3+C3
    则称 ( ABC ) 为水仙花数。

例如:三位数 153 ,其三位系数分别是:
1 3 + 5 3 + 3 3 = 1 + 125 + 27 = 153 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153 13+53+33=1+125+27=153

则 153 是水仙花数。

输入:

  • 无需输入

输出:

  • 由小到大输出满足条件的数,每个数单独一行。

示例输出:

text 复制代码
153
370
371
407

💯我的做法

我的做法如下:

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    for (int i = 100; i <= 999; i++) // 遍历所有三位数
    {
        int m = i; // 存储当前数字
        int count = 0; // 积累各位系数的立方和

        while (m)
        {
            int j = m % 10; // 取位:下一个位系数
            count += j * j * j; // 计算立方并积累
            m /= 10; // 清除最低位
        }

        if (count == i) // 检查积累立方和是否等于原数字
            cout << i << endl; // 输出
    }

    return 0;
}

思路分析

  1. 通过 for 循环遍历 [100, 999] 范围内的所有数字,以判断每个数字是否是水仙花数。
  2. 通过循环中的初始化:
    • 用临时变量 m 存储当前数字,无需直接操作原数。
    • 定义 count 用于积累各位系数立方和。
  3. 通过内部 while 循环:
    • 取位系数:通过 m % 10 获得最低位;
    • 计算立方值并积累:通过 j * j * j 直接计算立方值;
    • 清除最低位:通过 m /= 10,将数字左移一位;循环至数字为 0 为止。
  4. 检查立方积累和是否等于原数,如等,则输出。

优势

  • 简洁直观: 计算每个位系数立方直接通过三次乘法完成,避免使用更复杂的函数。
  • 处理简单: 通过循环直接完成数字分解、积累立方和,无需额外函数调用,更实用。

不足之处

  • 总处理时间复杂度为 ( O(n \times d) ),对于三位数,( d ) 是 3,因此复杂度为实际上是存在优化空间的,如果可直接计算各位,则可省去一些循环操作。
  • 输出格式比较基本,如需更好看的输出,可选择增加分隔符。

💯老师的做法

老师的代码如下:

cpp 复制代码
#include <iostream>
#include <cmath> // 引入函数 pow

using namespace std;

int main()
{
    for (int i = 100; i <= 999; i++) // 遍历所有三位数
    {
        int tmp = i; // 临时处理数字
        int ret = 0; // 积累各位系数立方和

        while (tmp)
        {
            ret += pow(tmp % 10, 3); // 取位和立方,使用pow函数
            tmp /= 10; // 清除最低位
        }

        if (ret == i) // 检查积累立方和是否等于原数
            cout << i << endl; // 输出
    }

    return 0;
}

思路分析

  1. 核心比较:使用 pow 函数计算立方:

    老师的做法并没有用直接乘法计算立方,而是使用了标准库中的 pow 函数。这样做的好处是:在基础程序教学中,比较直观,学生能学习标准函数的应用;同时使用 pow 计算任意次方,优质显而易见。

  2. 居有化简:进一步生成临时变量,直接取位计算,治理系统优化:

    基于基础计算源,老师用 tmp 分解,保留原数,从维护和计算的规范性方面,有较高的规范性和应用性。

优势

  • 可读性更好: 使用 pow 函数,明确表达了"次方"的概念,更便于基础教学和理解。
  • 通用性更强: 如需更改次方,可直接修改为 pow(tmp % 10, n) ,适配与任意次方计算,更具通用性。

不足

  • 性能突出较少: 使用 pow 函数导致调用源库,效率上不如直接乘法。在计算量不大时,注意不显著;但如若展开到更大的数据量,远不如乘法计算的效率高。

💯对比和优化

实现方式对比

方式 核心思想 优势 不足
我的做法 通过三次乘法直接计算立方 性能高,逻辑简洁,极对化 相对基础学生,学习成本较高
老师做法 使用 pow 函数计算立方 可读性好,通用性强 性能不如直接乘法,有调用源库的增加费用

优化思路和操作

在经典做法上,如下作举可能更加高效和实用:

1. 直接分解数字的各位

使用数学运算分解数字的各位,无需循环:

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    for (int i = 100; i <= 999; i++)
    {
        int a = i / 100;       // 百位
        int b = (i / 10) % 10; // 十位
        int c = i % 10;        // 个位

        if (i == a * a * a + b * b * b + c * c * c)
            cout << i << endl;
    }
    return 0;
}

这种做法可以直接获取各位,避免伴随调用和循环,效率更高。

2. 展开至任意位数水仙花数

通过使用函数展开计算任意位数的水仙花数:

cpp 复制代码
#include <iostream>
#include <cmath>
using namespace std;

// 检查水仙花数
bool isArmstrong(int n)
{
    int sum = 0, tmp = n;
    int digits = log10(n) + 1; // 位数

    while (tmp)
    {
        sum += pow(tmp % 10, digits); // 次方积累
        tmp /= 10;
    }
    return sum == n;
}

int main()
{
    for (int i = 100; i <= 999; i++)
    {
        if (isArmstrong(i))
            cout << i << endl;
    }
    return 0;
}

💯小结

通过对我和老师做法的分析,我们能看到:

  1. 核心思想相同: 我和老师都是通过数字分解和立方积累,实现水仙花数的检查。
  2. 实现途径带有小差异: 我的做法更重视性能,老师做法更重视可读性。
  3. 优化思考: 通过直接分解数字和展开至任意位数,可以更加高效和通用。

在实际经验中,可根据场景和需求选择最适合的方案,例如教学中选择通过性更强的方案,而在效率优先的场景下,可选择性能更高的直接乘法。求真时,始终是计算积累的深层探索!



相关推荐
Ronin-Lotus3 天前
蓝桥杯篇---IAP15F2K61S2串口
单片机·嵌入式硬件·职场和发展·蓝桥杯·c·iap15f2k61s2
Nicn6 天前
【C++初阶】类和对象①
c语言·开发语言·c++·算法·c·编程软件
Ronin-Lotus7 天前
蓝桥杯篇---实时时钟 DS1302
stm32·单片机·嵌入式硬件·职场和发展·蓝桥杯·c·ds1302
Ronin-Lotus9 天前
蓝桥杯篇---温度传感器 DS18B20
嵌入式硬件·职场和发展·蓝桥杯·c·ds18b20·iap15f2k61s2
IOT那些事儿12 天前
一个简单的Windows TCP服务器实现
服务器·windows·c·server·winsock2
飞翔的煤气罐boom15 天前
TCP服务器与客户端搭建
linux·tcp/ip·c
学习前端的小z16 天前
理解 C 与 C++ 中的 const 常量与数组大小的关系
c
Leon_Chenl16 天前
FFmpeg 头文件完美翻译之 libavdevice 模块
ffmpeg·音视频·c·编解码·libavdevice
学习前端的小z18 天前
【C语言】指针详解:概念、类型与解引用
c
学习前端的小z19 天前
【C++】B2122 单词翻转
c