Это может быть сделано с небольшой дозой математики.
Если вместо подсчета значений вы можете перечислить их, скажем, тридцать из них для 40, вы получите
[1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20, 21,
23, 24, 25, 27, 28, 29, 31, 32, 33, 35, 36, 37, 39, 40]
Если там сложно увидеть шаблон, попробуйте прочитать его вслух.Дело в том, что эти группы легко называются
[ 1,
3, 4, 5,
7, 8, 9,
11, 12, 13,
15, 16, 17,
19, 20, 21,
23, 24, 25,
27, 28, 29,
31, 32, 33,
35, 36, 37,
39, 40, (41)]
Другими словами, каждое четвертое число отсутствует, начиная с 2. Вот код, следующий за этим шаблоном:
const range = (lo, hi) => Array(...Array(hi - lo + 1)).map((_, n) => lo + n)
const countSquareable = (n) => range(1, n).filter(n => n % 4 !== 2).length
console.log(countSquareable(4))
console.log(countSquareable(5))
console.log(countSquareable(40))
console.log(countSquareable(45000))
Так что это соответствует ожиданиям.Но сейчас мы находимся на территории математики, поэтому нам нужно что-то доказать.Мы можем сделать это в трех случаях:
Можно ли представить n
в виде разности квадратов?
Случай 1: n
нечетный
Пусть a = (n + 1) / 2
, пусть b = (n - 1) / 2
.
Поскольку n
нечетно, n - 1
и n + 1
четные, поэтому a
и b
оба являются целыми числами.
a^2 = (n^2 + 2n + 1) / 4
b^2 = (n^2 - 2n + 1) / 4
поэтому
a^2 - b^2 = 4n / 4 = n
Следовательно, нечетное число может быть представлено как разность квадратов.
Случай 2: n делится на 4
Пусть a = (n / 4 + 1)
, пустьb = (n / 4 - 1)
Поскольку n
делится на 4, (n / 4) is an integer and thus
a and
b` являются целыми числами.
Now
a^2 = (n^2/16 + 2n/4 + 1)
b^2 = (n^2/16 - 2n/4 + 1)
и
a^2 - b^2 = 4n/4 = n
Следовательно, кратное 4 может быть представлено как разность квадратов.
Случай 3: кратное 2, не кратное 4
Мы можемразделите целые числа следующим образом: (4n), (4n + 1), (4n + 2), (4n + 3)
.
возводя в квадрат каждое из них и выбирая подходящее k
, мы получим:
(4n)^2 = 16n^2 = 4 * 4n^2 = (4k)
(4n + 1)^2 = (16n^2 + 8n + 1) = 4(4n^2 + 2n) + 1, = (4k + 1)
(4n + 2)^2 = (16n^2 + 16n + 4) = 4(4n^2 + 4n + 1) = (4k)
(4n + 3)^2 = (16n^2 + 24n + 9) = 4(4n^2 + 6n + 2) + 1 = (4k + 1)
Таким образом, единственные остатки, возможные при делении квадратана 4 равны 0 и 1.
Вычитая их, мы получаем (1 - 0) = 1
, (1 - 1) = 0
, (0 - 0) = 0
, (0 - 1) = -1
(этот последний аналогичен остатку 3: 4k - 1 = 4 (k -1) + 3.)
Таким образом, мы можем получитьостатки 0
, 1
или 3
.Но мы не можем получить 2
.
Следовательно, кратное 2, не кратное 4, не может быть представлено как разность квадратов.
QED Мы доказали, что наша интуиция верна: любое целое число может быть записано как разностьквадратов, за исключением тех, которые кратны 2, но не 4. 4. 1085 *
Обновление
Мой исходный код был методом грубой силы, отметив, что a^2 - b^2 = (a - b) * (a + b)
меньший коэффициент ((a - b)
) должен был быть меньше квадратного корня нашего верхнего числа, если произведение было бы меньше n
.Затем я попробовал все возможные значения b
, сохранив (a^2 - b^2)
, если оно было меньше n
.Это работает и кажется достаточно эффективным для случая 45000
.Но он пропускает анализ выше.
В любом случае, вот эта версия:
const countSquareable = (n) => {
const found = new Set()
// a^2 - b^2 = (a - b)(a + b), so (a - b) can be no larger than sqrt(n)
const topDiff = Math.sqrt(n)
for (let diff = 1; diff <= topDiff; diff++) {
const topB = n / 2 // can we get a tighter bound here?
for (let b = 0; b < topB; b++) {
let a = b + diff
const val = (a * a) - (b * b)
if (val <= n) {
found.add(val)
}
}
}
//console.log([...found].sort((a, b) => a - b))
return found.size
}
console.log(countSquareable(45000))