You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash计算小于N的3或5的倍数之和超时问题求助

Bash计算3或5倍数之和的性能优化思路

问题描述

计算小于N的所有3或5的倍数之和,输入格式为:

第一行是测试用例数T,随后T行每行是一个N值。

示例输入:

2
10
100

预期输出:

23
2318

用户的两种尝试均因速度未通过基准测试:

1. bc命令实现

#!/bin/bash
readarray input
printf 'n=%d-1; x=n/3; y=n/5; z=n/15; (1+x)*x/2*3 + (1+y)*y/2*5 - (1+z)*z/2*15\n' "${input[@]:1}" | bc

2. 纯Bash实现

#!/bin/bash
read t
while (( t-- ))
do
    read n
    echo "$(( --n, x=n/3, y=n/5, z=n/15, (1+x)*x/2*3 + (1+y)*y/2*5 - (1+z)*z/2*15 ))"
done

注:使用变量t是因为输入末尾没有换行符。


优化思路

1. 减少IO操作开销

原纯Bash实现每次循环都调用echo输出结果,多次IO操作会拖慢速度。可以先将所有计算结果存入数组,最后一次性批量输出:

#!/bin/bash
read -r t
results=()
while (( t-- )); do
    read -r n
    (( n--, x=n/3, y=n/5, z=n/15, sum=(1+x)*x/2*3 + (1+y)*y/2*5 - (1+z)*z/2*15 ))
    results+=("$sum")
done
printf '%s\n' "${results[@]}"

2. 简化数学公式,减少计算步骤

原公式可以合并为单次除法操作,减少算术运算次数:
原公式:3*(x*(x+1)/2) +5*(y*(y+1)/2) -15*(z*(z+1)/2)
简化后:(3*x*(x+1) +5*y*(y+1) -15*z*(z+1)) / 2
对应实现:

#!/bin/bash
read -r t
results=()
while (( t-- )); do
    read -r n
    (( n--, x=n/3, y=n/5, z=n/15, sum=(3*x*(x+1) +5*y*(y+1) -15*z*(z+1))/2 ))
    results+=("$sum")
done
printf '%s\n' "${results[@]}"

3. 批量读取输入,避免循环read

当测试用例数量极大时,循环read的开销明显。改用readarray一次性读取所有输入,再批量处理:

#!/bin/bash
readarray -t inputs
t=${inputs[0]}
results=()
for ((i=1; i<=t; i++)); do
    n=${inputs[i]}
    (( n--, x=n/3, y=n/5, z=n/15, sum=(3*x*(x+1) +5*y*(y+1) -15*z*(z+1))/2 ))
    results+=("$sum")
done
printf '%s\n' "${results[@]}"

4. 省略中间变量,直接内联计算

极端场景下,可以去掉中间变量x/y/z,直接在算术表达式中计算,减少变量赋值开销:

#!/bin/bash
readarray -t inputs
t=${inputs[0]}
results=()
for ((i=1; i<=t; i++)); do
    (( n=inputs[i]-1, sum=(3*(n/3)*((n/3)+1) +5*(n/5)*((n/5)+1) -15*(n/15)*((n/15)+1))/2 ))
    results+=("$sum")
done
printf '%s\n' "${results[@]}"

内容的提问来源于stack exchange,提问作者Fravadona

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 18:20:33