DC娱乐网

半小时找出9亿个数中的《神秘数字》这个程序有点厉害

小明最近在学编程,老师布置了一道有趣的题目:找出所有的9位水仙花数! 什么是水仙花数?水仙花数也叫阿姆斯特朗数,它有一个
小明最近在学编程,老师布置了一道有趣的题目:找出所有的9位水仙花数! 什么是水仙花数?水仙花数也叫阿姆斯特朗数,它有一个神奇的特点:一个n位数,其各位数字的n次幂之和等于这个数本身。 比如3位水仙花数:153 = 1³ + 5³ + 3³ 9位水仙花数就是:一个9位数,它的每一位数字的9次幂之和等于这个数本身。 听起来简单,对吧?但问题是:9位数有9亿个(从100,000,000到999,999,999)! 挑战来了老师还有一个要求:程序必须在30分钟内跑出结果。 小明算了算,如果用最笨的方法,每个数都要拆分成9位数字,然后计算9次方,再求和...这样肯定超时! 小明想出了优化方案1. 预计算,别做重复功每次都要计算数字的9次方?太浪费了!其实0-9每个数字的9次方是固定的: 0⁹ = 01⁹ = 12⁹ = 512...9⁹ = 387420489提前算好存起来,用的时候直接查表! # 预先计算好0-9的9次幂 power_9 = [0, 1, 512, 19683, 262144, 1953125, 10077696, 40353607, 134217728, 387420489] 2. 拆分数位有技巧怎么把一个9位数拆成单个数字?小明想到了用取余运算: num = 123456789 digits = [] while num > 0: digit = num % 10 # 取最后一位 digits.append(digit) num = num // 10 # 去掉最后一位 # 现在digits里就是[9,8,7,6,5,4,3,2,1] 3. 人多力量大,用多进程9亿个数太多了!小明看了看自己的电脑有8个CPU核心,能不能让它们一起工作呢? 把9亿个数分成8份,每个CPU核心处理一份,最后把结果汇总! 来看看最终的程序import time import multiprocessing def find_narcissistic_numbers(start, end, result_queue): """ 在指定范围内查找9位水仙花数(自幂数) 参数: start: 开始查找的数字(包含) end: 结束查找的数字(不包含) result_queue: 用于存储结果的队列 """ # 预先计算好的0-9的9次幂,避免重复计算 # 因为我们要找的是9位水仙花数,所以每个数字都要计算其9次方 ninth_powers = [ 0, # 0^9 1, # 1^9 512, # 2^9 19683, # 3^9 262144, # 4^9 1953125, # 5^9 10077696, # 6^9 40353607, # 7^9 134217728, # 8^9 387420489 # 9^9 ] found_numbers = [] # 遍历指定范围内的所有数字 for current_num in range(start, end): temp_num = current_num digit_sum = 0 # 分解数字的每一位,计算各位数字的9次方之和 while temp_num > 0: digit = temp_num % 10 # 获取最后一位数字 digit_sum += ninth_powers[digit] # 加上该位数字的9次方 temp_num //= 10 # 移除最后一位数字 # 检查是否为水仙花数 if digit_sum == current_num: found_numbers.append(current_num) # 将找到的结果放入队列 result_queue.put(found_numbers) def main(): """ 主程序:组织多进程查找9位水仙花数 """ print("Starting search for 9-digit narcissistic numbers...") start_time = time.time() # 定义9位数的范围 min_num = 100_000_000 # 最小的9位数 max_num = 999_999_999 # 最大的9位数 # 设置进程数量(可根据CPU核心数调整) num_processes = 8 # 计算每个进程需要处理的范围大小 range_per_process = (max_num - min_num) // num_processes # 准备进程列表和结果队列 processes = [] result_queue = multiprocessing.Queue() # 创建并启动多个进程,每个进程处理一个子范围 for i in range(num_processes): start_range = min_num + i * range_per_process # 如果是最后一个进程,确保覆盖到最大数 if i == num_processes - 1: end_range = max_num + 1 # +1 因为range不包含结束值 else: end_range = min_num + (i + 1) * range_per_process # 创建进程对象 process = multiprocessing.Process( target=find_narcissistic_numbers, args=(start_range, end_range, result_queue) ) processes.append(process) process.start() print(f"Process {i+1} started, processing range: {start_range} ~ {end_range-1}") # 等待所有进程完成 for process in processes: process.join() print("One process has finished its work") # 从队列中收集所有结果 all_narcissistic_numbers = [] while not result_queue.empty(): all_narcissistic_numbers.extend(result_queue.get()) # 对结果进行排序(从小到大) all_narcissistic_numbers.sort() # 计算总耗时 end_time = time.time() total_time = end_time - start_time # 输出结果 print("\n" + "="*50) print(f"Found {len(all_narcissistic_numbers)} 9-digit narcissistic numbers:") print("="*50) # 打印所有找到的水仙花数 for index, number in enumerate(all_narcissistic_numbers, 1): print(f"#{index:2}: {number}") print("\n" + "="*50) print(f"Total time: {total_time:.2f} seconds") print(f"Equivalent to: {total_time/60:.2f} minutes") # 检查是否在30分钟内完成 if total_time <= 4 30 146511208 472335975 534494836 912985153="=================================================" * 60: print("✅ successfully completed within minutes!") else: print("❌ exceeded minutes, further optimization needed") print("="*50) if __name__ == " __main__": """ 程序入口点 使用if __name__="=" "__main__"确保在多进程环境下正确运行 main() 程序运行结果小明运行了这个程序,他的电脑配置是: cpu:intel i7,8核心内存:16gb系统:windows 11程序运行了大约15分钟后,输出了结果:="=================================================" 找到了 个9位水仙花数:="=================================================" 第 1个: 2个: 3个: 4个: 总耗时: 896.52 秒 相当于: 14.94 分钟 ✅ 成功在30分钟内完成!="=================================================" 为什么这么快?预计算:0-9的9次幂只计算了10次,而不是9亿×9次多进程:8个CPU核心同时工作,速度提升近8倍高效算法:用取余和整除快速分离数字的每一位可以更优化吗?当然可以!小明后来还想到了一些优化方法: 进一步减少计算量:如果某个数的中间和已经超过原数,就可以提前结束使用数学特性:比如个位数字的特性可以帮助排除很多数更好的分配策略:动态分配任务,让快的进程多做一些小明的收获通过这个项目,小明学到了: 算法优化的重要性:同样的逻辑,优化后速度可以快几十倍并行计算的思想:把大任务拆分成小任务,同时处理数学与编程的结合:用数学思维指导编程优化最重要的是,小明明白了:编程不仅仅是写代码,更是思考如何用更聪明的方法解决问题。 试试看?如果你也想挑战一下,可以把代码复制到Python中运行,看看你的电脑需要多少时间! 小提示:如果你的电脑配置较低,可以把进程数调小一些,比如改成4个进程。 思考题:你能找到更快的算法吗?或者你能证明9位水仙花数只有这4个吗? 欢迎在评论区分享你的想法和结果!