如果一个数等于它的因数之和,那这个数就叫完美数,如28=1+2+4+7+14,如果它的因数之和小于这个数,那这个数叫做匮乏数,反之如果因数之和大于这个数,则成为丰富数
12是最小的丰富数,12 < 1+2+3+4+6,24是能被表示为2个丰富数之和的数中最小的那个,通过数学分析,所有比28123大的数都可以写成2个丰富数之和
求解:找到所有的不可以表示为2个丰富数之和的数,返回它们的和
pub fn solution() -> usize {
let mut abundant_arr = vec![];
let threshold = 28123;
for i in 12..=threshold {
if is_abundant(i) {
abundant_arr.push(i);
}
}
let abundant_arr_len = abundant_arr.len();
let mut target_arr: Vec<usize> = (0..=threshold).collect(); // 优化点1
for i in 0..abundant_arr_len {
for j in i..abundant_arr_len { // 优化点4
let s = abundant_arr[i] + abundant_arr[j];
if s <= threshold {
target_arr[s] = 0; // 优化点2
}
}
}
return target_arr.iter().sum();
}
fn is_abundant(num: usize) -> bool {
let mut divisor_sum = 1;
let mid = (num as f64).sqrt() as usize + 1; // 优化点3
for i in 2..mid+1 {
if num % i == 0 {
let q = num / i;
if i < q {
divisor_sum += i;
divisor_sum += q;
}
if i == q {
divisor_sum += i;
}
}
}
if divisor_sum > num {
return true;
}
return false;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_abundant() {
for i in 1..12 {
assert_eq!(false, is_abundant(i));
}
assert_eq!(true, is_abundant(12));
assert_eq!(false, is_abundant(13));
assert_eq!(false, is_abundant(16));
assert_eq!(true, is_abundant(4088));
assert_eq!(true, is_abundant(20));
assert_eq!(false, is_abundant(28)); // 28 is perfect number, so not abundant number
}
#[test]
fn test_solution() {
assert_eq!(4179871, solution());
}
}
基本思路是先把[12, 28123]之间的丰富数都提取出来存放到一个数组中,大概有6000多个这样的数,遍历2遍这个数组,找出能表示为2个丰富数之和的数剔除出来,剩下的就是不能被表示的,然后求和就行了。代码后面按照惯例包含单测和功能测试