Всем привет. Меня зовут Елена, и на канале TeachYOU мы разбираем темы и задачи из ЕГЭ по информатике. Изначально я планировала писать статьи по базовым темам, но этот материал будет на тему делителей числа — то, что встречается в 25м прототипе. По моему мнению, этот материал относится к разряду тех, что нужно осознать один раз и в дальнейшем просто пользоваться этими соображениями.
Пример задачи
Рассмотрим задачу 22 с сайта kompege.ru .
Напишите программу, которая ищет среди целых чисел, принадлежащих числовому отрезку [174457; 174505], числа, имеющие ровно два различных натуральных делителя, не считая единицы и самого числа. Для каждого найденного числа запишите эти два делителя в таблицу на экране с новой строки в порядке возрастания произведения этих двух делителей. Делители в строке таблицы также должны следовать в порядке возрастания.
Далее я предполагаю, что вы знакомы с принципами программирования.
Предлагаю сначала решить эту задачу «в лоб»:
1) циклом перебираем числа из диапазона [174457; 174505], записываем их в переменную x.
Люди, Превратившие Себя В Жутких Кукол
2) для каждого числа х будем искать делители и считать их. Заведем список dels = [] — в него будем записывать делители числа x.
а) так как нам не нужно находить тривиальные делители (единицу и само число), будем искать делители среди чисел d из диапазона [2, x-1].
б) для каждого числа d проверяем, является ли оно делителем числа x (если является, то остаток от деления x на d равен нулю). Если является — добавляем делитель d в список dels .
в) после того, как перебрали все числа d — «возможные делители», проверяем количество делителей в списке dels . Если их два — выводим эти делители на экран.
3) если перебрали не все числа x, возвращаемся к п.1)
Ниже размещаю листинг кода, ссылка на программу тут .
Добавила вывод времени выполнения программы, чтобы мы далее могли сравнить производительность разных кодов. Отмечу, что пользовалась онлайн-компилятором, поэтому думаю, что время выполнения может быть неточным. Но для сравнения разных кодов такой величины будет достаточно.
Немного оптимизируем
Сокращение диапазона поиска возможных делителей
Рассмотрим число 12 . Кроме тривиальных, его делителями являются числа 2, 3, 4, 6 . Можно заметить, что его максимальный делитель равен 12 // 2 . Получается, что возможные делители числа x находятся в диапазоне [2; x // 2] (здесь // — обозначает операцию целочисленного деления — взятия целой части от деления). Давайте изменим этот момент в коде и посмотрим, как меняется время выполнения программы:
Введение функции break
Также можно отметить, что если в списке dels уже есть три делителя, дальше проверять, являются ли числа d делителями, бессмысленно — все равно данное число x не подходит для ответа (ищем числа с двумя нетривиальными делителями). Поэтому можно прервать цикл по возможным делителям с помощью оператора досрочного выхода из цикла break .
Будущее Беларуси: что и как может резко его изменить? Экспертно-аналитический клуб
Такая небольшая оптимизация позволила нам ускорить программу почти в десять раз!
Интересное о делителях
Для дальнейшей оптимизации нужно узнать/осознать/вспомнить кое-что о делителях.
Еще раз рассмотрим число 12 и его делители:
Делаем вывод, что, если у числа x четное количество делителей n , то, зная первые (минимальные) n // 2 делителей, можем найти его оставшиеся делители как частное от числа x и его известных делителей.
Появляются вопросы:
- Где проходит граница диапазона для поиска минимальных делителей?
- А что, если у числа нечетное количество делителей?
Начнем со второго вопроса.
Рассмотрим делители числа 16:
Восемь идет в паре с двойкой и должна быть такого же цвета. Но картинка упорно сохраняется с черной восьмеркой
Как и следовало ожидать, если количество делителей нечетно — один из них будет непарным. Но на самом деле он парен самому себе: 4*4 = 16.
Делаем важный вывод. У числа x будет нечетное количество делителей тогда и только тогда, когда есть число y, такое, что y * y = x. Другими словами , если число является квадратом другого числа, у него нечетное количество делителей (и наоборот).
И вывод (или замечание) второе — граница поиска минимального делителя числа x проходит по значению корня из числа х.
Получается, что процедуру поиска делителей числа x можно разбить на части:
- Вычисление границы диапазона поиска наименьших делителей.
- Поиск наименьших делителей в этом диапазоне.
- Если в задаче нужно определить количество делителей — умножаем количество наименьших делителей на два. Если нужно напрямую вычислить делители — находим их как частное от деления числа x на известные делители.
- Если число является полным квадратом — добавляем этот делитель в список уже найденных (или увеличиваем количество делителей на единицу).
Звучит логично и несложно, но на самом деле определение, является ли число полным квадратом, не такая простая задача из-за погрешности вычислений. Этот момент оставим пока в стороне и вернемся к задаче поиска чисел с двумя нетривиальными делителями.
Окончательная оптимизация
Изменим программу, приведенную выше.
Во-первых, будем добавлять в список делитель d и сразу его пару x // d .
Во-вторых, уменьшим диапазон для поиска наименьших делителей d . Следует отметить, что есть разные пути реализации диапазона (кстати, мы не можем просто взять диапазон [2, round(x ** 0.5)] — если интересно, проверьте, в каких границах будете искать делители для чисел 12, 15, 16). Я предлагаю взять диапазон с запасом, например , [2, round(x ** 0.5) + 1] и добавить проверку — если делитель в квадрате равен числу x , то в список делителей добавляем его без пары; если квадрат делителя больше числа x — делаем break . Такая реализация будет достаточно строгой — мы точно переберем все нужные числа и не посчитаем какие-то делители дважды.
Программу можете найти по ссылке здесь . Листинг привожу на картинке.
Источник: dzen.ru
Измените программу так чтобы с ее помощью можно было найти наибольший
var
i,a,b,c:integer;
begin
Randomize;
for i:=1 to 10 do begin
a:=Random(99)+1;
b:=Random(99)+1;
Euclid(a,b,c);
Writeln(НОД(,a. b,)=,c)
end
end.
Оцени ответ
- Алгебра
- Математика
- Русский язык
- Українська мова
- Информатика
- Геометрия
- Химия
- Физика
- Экономика
- Право
- Английский язык
- География
- Биология
- Другие предметы
- Обществознание
- История
- Литература
- Українська література
- Беларуская мова
- Қазақ тiлi
Показать ещё
Источник: www.shkolniku.com
Измените программу так, чтобы с ее помощью можно было найти:
а) максимальное из чисел a, b, c:
б) максимальное из чисел b, c, d
в) минимальное из 4 чисел:
г) разность максимального и минимального из 4 чисел
Помогите пожалуйста!
а) Вместо строчки f := max(max(a, b), max(c,d)); Вставить строчку f := max(max(a, b), c); б) Вместо строчки f := max(max(a, b), max(c,d)); Вставить строчку f := max(max(b, c), d); в) Добавить функцию function min (x, y: integer): integer; begin if x > y then min := y else min := x; end Вместо строчки f := max(max(a, b), max(c,d)); Вставить строчку f := min(min(a, b), min(c,d)); г) (с добавленной функцией из пункта в) . ) Вместо строчки f := max(max(a, b), max(c,d)); Вставить строчку f := max(max(a, b), max(c, d)) — min(min(a, b), min(c, d));
Добавить свой ответ Ответить на вопрос
Еще вопросы
Источник: znanija.site