You can simplify the arithmetic by using
(n + 1)**2 == n**2 + (2*n + 1)
Here’s how to do that using a generator function:
import math
def squares(lo, hi):
root = int(math.ceil(lo ** 0.5))
num = root ** 2
delta = 2 * root + 1
while num <= hi:
yield num
num += delta
delta += 2
print list(squares(4, 16))
print list(squares(5, 50))
print list(squares(20, 90))
output
[4, 9, 16]
[9, 16, 25, 36, 49]
[25, 36, 49, 64, 81]
Here’s an equivalent iterator class. I’ve given it a __repr__
method so it looks nice if you print an instance of this class.
import math
class Squares(object):
def __init__(self, start, stop):
self.start = start
self.stop = stop
root = int(math.ceil(start ** 0.5))
self.num = root ** 2
self.delta = 2 * root + 1
def __repr__(self):
return 'Squares(%d, %d)' % (self.start, self.stop)
def __iter__(self):
return self
def next(self):
num = self.num
if num > self.stop:
raise StopIteration
self.num += self.delta
self.delta += 2
return num
sq = Squares(4, 16)
print sq
for i in sq:
print i
print list(Squares(5, 50))
print list(Squares(20, 90))
output
Squares(4, 16)
4
9
16
[9, 16, 25, 36, 49]
[25, 36, 49, 64, 81]
For Python 3, replace the next
method name with __next__
.
The usual Python range
convention is to stop before you reach the high limit. To make this code comply with that convention, in the squares()
generator change
while num <= hi:
to
while num < hi:
and in the Squares()
class, change
if num > self.stop:
to
if num >= self.stop:
0 / 0 / 0 Регистрация: 15.04.2022 Сообщений: 1 |
|
1 |
|
15.04.2022, 10:57. Показов 6251. Ответов 20
Необходимо найти все числа на отрезке от А до B (А и B вводим) , которые являются полными квадратами. Если в заданном диапазоне таких чисел нет вывести -1. Пример вводных данных и ответа : Ввод : 1 30 Ввод : 10 50
0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
15.04.2022, 10:57 |
20 |
Пифагор 2169 / 1652 / 840 Регистрация: 10.01.2015 Сообщений: 5,184 |
||||
15.04.2022, 11:57 |
2 |
|||
1 |
eaa |
15.04.2022, 13:28
|
Не по теме: Пифагор, медленно) можно быстрее же посчитать
0 |
Пифагор 2169 / 1652 / 840 Регистрация: 10.01.2015 Сообщений: 5,184 |
||||
15.04.2022, 13:37 |
4 |
|||
eaa, а почему “не по теме”? Полагаю, через циклы без
0 |
Gdez 7254 / 4043 / 1779 Регистрация: 27.03.2020 Сообщений: 6,869 |
||||
15.04.2022, 13:49 |
5 |
|||
Пифагор,
0 |
2169 / 1652 / 840 Регистрация: 10.01.2015 Сообщений: 5,184 |
|
15.04.2022, 14:00 |
6 |
Gdez, это получается быстрее? Тут и модуль подключается, и приведение к типу, и создание списка, и сам
0 |
Gdez 7254 / 4043 / 1779 Регистрация: 27.03.2020 Сообщений: 6,869 |
||||
15.04.2022, 14:06 |
7 |
|||
Пифагор,
1 |
2169 / 1652 / 840 Регистрация: 10.01.2015 Сообщений: 5,184 |
|
15.04.2022, 14:26 |
8 |
Gdez, а за счет чего код так быстро исполняется?
0 |
7254 / 4043 / 1779 Регистрация: 27.03.2020 Сообщений: 6,869 |
|
15.04.2022, 14:32 |
9 |
Пифагор, допустим диапазон = [1, 100]. Он содержит 10 полных квадратов. У меня счетчик цикла == 10. У Вас == 100
1 |
2169 / 1652 / 840 Регистрация: 10.01.2015 Сообщений: 5,184 |
|
15.04.2022, 14:42 |
10 |
Gdez, цифры увидел, но не совсем понял, как они формируются. В данном случае, 10 циклов вместо 100 получается из-за отсутствия ветвления и сравнения?
0 |
7254 / 4043 / 1779 Регистрация: 27.03.2020 Сообщений: 6,869 |
|
15.04.2022, 15:38 |
11 |
Пифагор,
1 |
Catstail Модератор 35328 / 19429 / 4065 Регистрация: 12.02.2012 Сообщений: 32,458 Записей в блоге: 13 |
||||
15.04.2022, 16:21 |
12 |
|||
Не могу одобрить эти коды. Они используют плавающую точку, а значит для 16-и и более разрядных чисел начнут безбожно врать. Смотрите:
3 |
enx |
15.04.2022, 17:11
|
Не по теме: Catstail, как всегда, чистая алгоритмическая магия :drink:
0 |
eaa Status 418 3840 / 2124 / 568 Регистрация: 26.11.2017 Сообщений: 4,986 Записей в блоге: 2 |
||||
15.04.2022, 22:59 |
14 |
|||
1 |
Модератор 35328 / 19429 / 4065 Регистрация: 12.02.2012 Сообщений: 32,458 Записей в блоге: 13 |
|
16.04.2022, 11:10 |
15 |
eaa, да… Но интересно же сделать самому.
0 |
Status 418 3840 / 2124 / 568 Регистрация: 26.11.2017 Сообщений: 4,986 Записей в блоге: 2 |
|
16.04.2022, 11:40 |
16 |
Catstail, полностью согласен. Но этот бин.поиск будет медленный. когда много чисел близких к 1018 из которых нужно корень вычислять. нужно другой писать, isqrt быстрый.
0 |
Модератор 35328 / 19429 / 4065 Регистрация: 12.02.2012 Сообщений: 32,458 Записей в блоге: 13 |
|
16.04.2022, 12:39 |
17 |
eaa, а есть более быстрые алгоритмы? Бин поиск – логарифмический.
0 |
Status 418 3840 / 2124 / 568 Регистрация: 26.11.2017 Сообщений: 4,986 Записей в блоге: 2 |
|
16.04.2022, 13:38 |
18 |
Catstail, если взять не икс пополам правую границу. Добавлено через 51 минуту
1 |
Модератор 35328 / 19429 / 4065 Регистрация: 12.02.2012 Сообщений: 32,458 Записей в блоге: 13 |
|
16.04.2022, 14:00 |
19 |
eaa, а как он реализован? На Питоне? Добавлено через 4 минуты
0 |
Status 418 3840 / 2124 / 568 Регистрация: 26.11.2017 Сообщений: 4,986 Записей в блоге: 2 |
|
16.04.2022, 14:37 |
20 |
модуль math, на си же.
метод Ньютона тот же бинпоиск.
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
16.04.2022, 14:37 |
Помогаю со студенческими работами здесь Найти количество чисел, которые не превосходят числа A и являются полными квадратами некоторого натурального числа Найти произведение чисел, которые не превосходят 4000 и являются полными квадратами некоторого натурального числа Есть ли совершенные числа из промежутка [2, n], которые являются полными квадратами Найдите все числа, являющиеся полными квадратами, на отрезке от A до B Выведите все числа на отрезке от a до b, являющиеся полными квадратами Искать еще темы с ответами Или воспользуйтесь поиском по форуму: 20 |
Вы можете упростить арифметику, используя
(n + 1)**2 == n**2 + (2*n + 1)
Здесь, как это сделать, используя функцию генератора:
import math
def squares(lo, hi):
root = int(math.ceil(lo ** 0.5))
num = root ** 2
delta = 2 * root + 1
while num <= hi:
yield num
num += delta
delta += 2
print list(squares(4, 16))
print list(squares(5, 50))
print list(squares(20, 90))
Выход
[4, 9, 16]
[9, 16, 25, 36, 49]
[25, 36, 49, 64, 81]
Здесь эквивалентный класс итератора. Я дал ему метод __repr__
, поэтому он выглядит хорошо, если вы печатаете экземпляр этого класса.
import math
class Squares(object):
def __init__(self, start, stop):
self.start = start
self.stop = stop
root = int(math.ceil(start ** 0.5))
self.num = root ** 2
self.delta = 2 * root + 1
def __repr__(self):
return 'Squares(%d, %d)' % (self.start, self.stop)
def __iter__(self):
return self
def next(self):
num = self.num
if num > self.stop:
raise StopIteration
self.num += self.delta
self.delta += 2
return num
sq = Squares(4, 16)
print sq
for i in sq:
print i
print list(Squares(5, 50))
print list(Squares(20, 90))
Выход
Squares(4, 16)
4
9
16
[9, 16, 25, 36, 49]
[25, 36, 49, 64, 81]
Для Python 3 замените имя метода next
на __next__
.
Обычное соглашение Python range
должно остановиться, прежде чем вы достигнете верхнего предела. Чтобы этот код соответствовал этому соглашению, в смене генератора squares()
while num <= hi:
to
while num < hi:
и в классе squares()
измените
if num > self.stop:
to
if num >= self.stop:
Формулировка задачи:
Код к задаче: «Найти квадраты чисел, не превышающих 15»
textual
var i, a : integer; begin i:=1; repeat a:=i; a:=sqr(a); Write(a, ' '); i:=i+1; until i>15; end.
Полезно ли:
15 голосов , оценка 3.467 из 5
Вопрос:
Учитывая два числа x
и y
, найдите количество чисел, свободных от квадратов, где квадратное число равно делимому без идеального квадрата, кроме 1
. Например, 10
является квадратным, но 18
не является, поскольку он делится на 9 = 32
. Несколько положительных квадратов свободных чисел:
1, 2, 3, 5, 6, 7, 10, 11, 13, 14, 15 ...
пределы
1 <= X,Y <= 10^9
0 <= |X-Y| <= 10^6
x=10 , Y=15
дает
ans=5
Мой подход состоит в том, чтобы сгенерировать все простые до squareroot(10^9)
(сито эратосфенов) и проверить, будет ли каждое число в заданном диапазоне делиться на квадрат простого числа. Граф таких чисел вычитается из длины диапазона, чтобы получить квадратные свободные числа.
Но этот подход требует сложной работы, пожалуйста, предложите другой подход
Лучший ответ:
Используйте принцип исключения включения:
Пусть f(n) = number of non-square-free numbers in 1 ... n
. Мы будем делать исключение включения только на квадраты простых чисел, чтобы избежать перерасчета квадратов квадратов.
Имеем:
f(n) = n / 4 => these are divisible by 4, so NOT square-free
+
n / 9 => these are divisible by 9, so NOT square-free
+
n / 25 => these are divisible by 16, so NOT square-free
+
...
-
n / (4*9) => these are divisible by both 4 and 9, so we overcounted
-
n / (4*25) => these are divisible by both 4 and 25, so we overcounted
-
...
Насколько это эффективно?
Нам нужны только числа p
такие, что p^2 <= 10^9
, что означает p < 31623
. Это уже не много простых, любое тривиальное сито (или, может быть, даже пробное деление) должно быть достаточно быстрым. Затем примените включение-исключение, которое также будет быстрым, так как продукты квадратов простых чисел будут быстро развиваться, поэтому вы сможете завершить преждевременно во многих случаях (n / something = 0
всякий раз, когда something > n
).
Чтобы понять, почему вы сможете досрочно прекратить работу, перепишите выше:
f(n) = n / (2^2) -
n / (2^2*3^2) +
n / (2^2*3^2*5^2) - <= this becomes 0 very fast.
When it does,
backtrack and increment the previous term.
For example, if this were 0,
you'd do - n / (2^2*5^2) next
...
Подробнее об этом здесь.
Ответ №1
Чтобы развернуть мой комментарий: предположим, что X <= Y и инициализировать булевский массив SF [X..Y], чтобы быть истинным. Для каждого k от 2 до пола (sqrt (Y)) (необязательно включая композиты, асимптотическое время работы остается неизменным), для каждого кратного m k² между X и Y установите SF [m] в false. Верните количество истинных значений, оставшихся в SF.
Время работы O ((Y – X) + sqrt (Y)), так как Σ k = 1,…, ∞ 1/k² = π²/6.