Как найти произведение больше n числа

0 / 0 / 0

Регистрация: 13.12.2021

Сообщений: 3

1

19.11.2022, 10:07. Показов 362. Ответов 3


Студворк — интернет-сервис помощи студентам

Дана последовательность целых положительных чисел. Найти произведение только тех чисел, которые больше заданного числа N. Если таких нет, выдать соответствующее сообщение

Вход:

10

3 5 7 1 12 48

Выход :

576



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

19.11.2022, 10:07

3

Mikail7D6

beginner

296 / 208 / 98

Регистрация: 02.08.2022

Сообщений: 336

19.11.2022, 11:51

2

Лучший ответ Сообщение было отмечено Vladlen9087 как решение

Решение

Vladlen9087,

Python
1
2
3
4
5
6
from math import prod
 
n = int(input())
arr = map(int, input().split())
 
print(prod(i for i in arr if i > n))



1



thyrex

Вирусоборец

11453 / 6546 / 1357

Регистрация: 06.09.2009

Сообщений: 24,739

19.11.2022, 12:05

3

Mikail7D6,

Bash
1
2
3
4
5
6
Ввод
50
3 5 7 1 12 48
 
Вывод
1



0



Mikail7D6

beginner

296 / 208 / 98

Регистрация: 02.08.2022

Сообщений: 336

19.11.2022, 12:14

4

Python
1
2
3
4
5
6
7
from math import prod
 
n = int(input())
arr = map(int, input().split())
lst = prod(i for i in arr if i > n)
 
print(('empty', lst)[lst > 1])



1



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

19.11.2022, 12:14

Помогаю со студенческими работами здесь

Найти произведение только тех чисел, которые больше заданного числа
дана последовательность целых положительных чисел. найти произведение только тех чисел, которые…

Найти произведение только тех чисел, которые больше заданного числа m
Составить программу на Паскале, содержащую минимум 4 подпрограммы.
Дан одномерный массив,…

Найти произведение только тех чисел, которые больше заданного числа М
Дана последовательность целых положительных чисел. Найти произведение только тех чисел, которые…

Найти произведение только тех чисел, которые больше заданного числа М
Решите плиззз

Дана последовательность целых положительных чисел найти произведение только тех из…

Найти произведение только тех чисел, которые больше заданного числа М
дана последовательность целых положительных чисел. Найти произведение только тех чисел, которые…

Найти произведение только тех чисел массива, которые больше заданного числа
Дана последовательность целых положительных чисел.
Найти произведение только тех чисел, которые…

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

4

Разберём чуть более сложную задачу. Итак, вам дана последовательность неотрицательных целых чисел $a_1, dots, a_{n}$. Вычислите

$$
maxlimits_{1 le i neq j le n}a_i cdot a_j , .
$$

Обратите внимание, что $i$ и $j$ должны быть разными, хотя в каких-то случаях можно наблюдать, что $a_i=a_j$.

  • Формат ввода: Первая строка содержит целое число $n$. Следующая строка содержит $n$ неотрицательных целых чисел $a_1, dotsc, a_{n}$ (разделены пробелами).
  • Формат вывода: Максимальное попарное произведение.
  • Ограничения: $2 le n le 2cdot10^5$; $0 le a_1, dots, a_{n} le 2cdot 10^5$.
  • Примеры

Пример 1

Ввод Вывод
3
1 2 3
6

Пример 2

Ввод Вывод
10
7 5 14 2 8 8 10 1 2 3
140

макс-произвед_01.svg

Наивный подход

Наивный способ решить задачу Максимальное произведение — перебрать все возможные пары вводных элементов $A[1dotsc n]=[a_1,dotsc, a_n]$ и найти пару, которая даёт наибольшее произведение.

MaxPairwiseProductNaive(A[1..n]):
    product = 0
    for i from 1 to n
        for j from 1 to n
            if i != j
                if product < A[i] * A[j]
                    product = A[i] * A[j]
    return product

Этот код можно оптимизировать и сократить следующим образом.

MaxPairwiseProductNaive(A[1..n]):
    product = 0
    for i from 1 to n
        for j from i+1 to n
            product = max(product, A[i] * A[j])
    return product

Реализуйте этот алгоритм, используя ваш любимый язык программирования. Если вы используете C++, Java или Python3, вам могут пригодиться начальные заготовки (для всех задач из книги мы предлагаем стартовые заготовки с использованием этих трёх языков в интерфейсе тестирующей системы).
С другими языками вам понадобится сделать работу с нуля.

Стартовые заготовки решений для C++, Java и Python3 представлены ниже.

C++

#include <iostream>
#include <vector>
#include <algorithm>

int MaxPairwiseProduct(const std::vector<int>& numbers) {
    int max_product = 0;
    int n = numbers.size();

    for (int first = 0; first < n; ++first) {
        for (int second = first + 1; second < n; ++second) {
            max_product = std::max(max_product,
                numbers[first] * numbers[second]);
        }
    }

    return max_product;
}

int main() {
    int n;
    std::cin >> n;
    std::vector<int> numbers(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> numbers[i];
    }

    std::cout << MaxPairwiseProduct(numbers) << "n";
    return 0;
}

Java

import java.util.*;
import java.io.*;

public class MaxPairwiseProduct {
    static int getMaxPairwiseProduct(int[] numbers) {
        int max_product = 0;
        int n = numbers.length;

        for (int first = 0; first < n; ++first) {
            for (int second = first + 1; second < n; ++second) {
                max_product = Math.max(max_product,
                    numbers[first] * numbers[second]);
            }
        }

        return max_product;
    }

    public static void main(String[] args) {
        FastScanner scanner = new FastScanner(System.in);
        int n = scanner.nextInt();
        int[] numbers = new int[n];
        for (int i = 0; i < n; i++) {
            numbers[i] = scanner.nextInt();
        }
        System.out.println(getMaxPairwiseProduct(numbers));
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        FastScanner(InputStream stream) {
            try {
                br = new BufferedReader(new
                    InputStreamReader(stream));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }
    }

}

Python

def max_pairwise_product(numbers):
    n = len(numbers)
    max_product = 0
    for first in range(n):
        for second in range(first + 1, n):
            max_product = max(max_product,
                numbers[first] * numbers[second])

    return max_product


if __name__ == '__main__':
    _ = int(input())
    input_numbers = list(map(int, input().split()))
    print(max_pairwise_product(input_numbers))

После проверки вы можете увидеть такое сообщение:

Failed case #4/17: time limit exceeded

Дело в том, что мы проверяем ваше решение на тестовых примерах — это помогает убедиться, что программа работает быстро и без ошибок.
В результате мы, как правило, знаем, какие ошибки вы допустили.
Сообщение выше говорит о том, что предложенная программа превышает ограничение по времени в 4-м тестовом примере из 17.

💡 Остановитесь и подумайте:
Почему решение не укладывается в ограничение по времени?

MaxPairwiseProductNaive выполняет порядка $n^2$ шагов при последовательности длиной $n$.
При максимальном возможном значении $n=2cdot 10^5$ количество шагов будет порядка $4cdot 10^{10}$.
Так как большинство современных компьютеров выполняют около $10^8$–$10^9$ базовых операций в секунду (разумеется, это зависит от компьютера),
выполнение MaxPairwiseProductNaive может занять десятки секунд.
Это превысит временное ограничение задачи.

Нам нужен более быстрый алгоритм!

Быстрый алгоритм

А что если внимательнее рассмотреть более мелкие примеры— скажем, $[5,6,2,7,4]$? Эврика! Достаточно помножить два самых больших элемента массива — $7$ и $6$.

То есть нам достаточно просканировать последовательность лишь дважды. При первом сканировании мы найдем самый большой элемент, затем — второй по величине.

MaxPairwiseProductFast(A[1..n]):
    index_1 = 1
    for i from 2 to n
        if A[i] > A[index_1]
            index_1 = i
    index_2 = 1
    for i from 2 to n
        if A[i] != A[index_1] and A[i] > A[index_1]
            index_1 = i
    return A[index_1] * A[index_2]

Тестирование и отладка

Реализуйте этот алгоритм и протестируйте его на вводе $A=[1,2]$. Как и ожидалось, алгоритм выводит $2$.
Затем проверьте на вводе $A=[2,1]$. На удивление, алгоритм выводит $4$.
Изучив код, вы обнаружите, что после первого цикла $index_1=1$. Далее алгоритм инициализирует $index_2$ значением $1$, и цикл for не обновляет $index_2$.
В результате перед возвратом $index_1=index_2$. Чтобы этого избежать, необходимо изменить псевдокод следующим образом:

MaxPairwiseProductFast(A[1..n]):
    index_1 = 1
    for i from 2 to n
        if A[i] > A[index_1]:
            index_1 = i
    if index_1 = 1
        index_2 = 2
    else:
        index_2 = 1
    for i from 1 to n
        if A[i] != A[index_1] and A[i] > A[index_1]
            index1 = i
    return A[index_1] * A[index_2]

Опробуйте этот код на маленьких наборах данных $[7,4,5,6]$, чтобы убедиться, что он выдает правильные результаты. Затем попробуйте ввод.

2  
100000 90000  

Может оказаться, что программа выдает что-то вроде $410,065,408$ или даже отрицательное число вместо правильного результата — $9,000,000,000$.
Вероятнее всего, это вызвано целочисленным переполнением. Например, на языке C++ такое большое число, как $9,000,000,000$, не умещается в стандартный тип int, который занимает 4 байта на большинстве компьютеров и варьируется от $-2^{31}$ до $2^{31}-1$ при
$$
2^{31}=2,147,483,648 ,.
$$

Соответственно, вместо использования типа int в C++ при вычислении произведения и сохранении результата вам нужно использовать тип int64_t.
Это предотвратит целочисленное переполнение, так как тип int64_t занимает 8 байтов и хранимые значения варьируются от $-2^{63}$ до $2^{63}-1$ при

$$
2^{63}=9,223,372,036,854,775,808 , .
$$

Затем протестируйте вашу программу с большими наборами данных, например, с массивом $A[1 dotsc 2 cdot 10^5]$, где $A[i]=i$ для всех $1 le i le 2 cdot 10^5$.
Это можно сделать двумя способами:

  • Создать массив в программе и передать его MaxPairwiseProductFast (чтобы не считывать его из стандартного ввода).
  • Создать отдельную программу, которая запишет такой массив в файл dataset.txt. Затем передать этот набор данных вашей программе из консоли:
yourprogram < dataset.txt

Убедитесь, что при обработке данных ваша программа укладывается в ограничение по времени и выдаёт верный результат: $39,999,800,000$.
Теперь вы можете быть уверенным, что ваша программа работает!

Однако система оценки снова ругается:

Failed case #5/17: wrong answer

Но как создать такой тестовый сценарий, который приведет к сбою программы и поможет понять, что с ней не так?

А в чём ошибка?

Вероятно, вас интересует, почему мы не предоставили 5-й набор данных из 17 — тот, который привел к сбою программы?
Причина проста: в реальности вам не будут показывать тестовые примеры.

Даже опытные программисты при решении задач с алгоритмами часто совершают ошибки, которые трудно обнаружить.
Поэтому важно научиться находить баги как можно раньше.
Когда авторы этой книги только начинали программировать, они ошибочно полагали, что почти все их программы правильные.
Сейчас же мы знаем, что при первом запуске наши программы почти никогда не верны.

Когда разработчик уверен в работе своей программы, он зачастую использует всего лишь несколько примеров для тестирования.
Если результаты выглядят приемлемо, он считает свою работу законченной — но это путь к катастрофе.
Если вы хотите убедиться, что ваша программа работает всегда, то советуем тщательно подобрать примеры для тестирования.
Реализация алгоритмов, а также их тестирование и отладка будут бесценным навыком для вашей будущей карьеры программиста.

Стресс-тестирование

Представляем вам стресс-тестирование — технику, которая позволяет генерировать тысячи тестовых сценариев. С её помощью можно найти тот, из-за которого провалилось ваше решение.

Стресс-тестирование состоит из четырёх частей:

  • Реализация алгоритма.
  • Альтернативная, банальная и медленная, но правильная реализация алгоритма для той же самой задачи.
  • Генератор случайных тестов.
  • Бесконечный цикл, генерирующий тесты и передающий их обоим вариантам реализации для сравнения результатов. Если результаты разнятся, выводятся оба результата и пример для тестирования, а программа останавливается. В ином случае цикл повторяется.

Стресс-тестирование основано на идее, что две правильных реализации
с каждым тестом должны приводить к одному ответу (при условии, что ответ на задачу уникален).
Однако если одна из реализаций неправильна, должен существовать такой тест, который приводит к разным ответам.
Единственный случай, при котором это не так, — когда в обеих реализациях есть одна и та же ошибка.
Но это маловероятно — если ошибка не где-то в программе ввода/вывода, общей для обоих решений.
Действительно, если одно решение правильно, а другое — нет, то существует сценарий тестирования, при котором они различаются.
Если оба решения неверны, но баги отличаются — скорее всего, есть тест, при котором два решения дают разные результаты.

Продемонстрируем стресс-тестирование MaxPairwiseProductFast,
используя

MaxPairwiseProductNaive в качестве тривиальной реализации:

StressTest(N, M):
    while true:
        n = ... // случайное целое число между 2 и N
        // создать массив A[1..n]
        for i from 1 to n
            A[i] = ... // случайное целое число между 0 и M
        print(A[1..n])
        result_1 = MaxPairwiseProductNaive(A)
        result_2 = MaxPairwiseProductFast(A)
        if result_1 = result_2:
            print("OK")
        else:
            print("Wrong answer:", result_1, result_2)
            return

Представленный выше цикл while сначала генерирует длину вводной последовательности $n$, случайное число между $2$ и $N$.
Оно должно быть не менее $2$: формулировка задачи гласит, что $n ge 2$.
Параметр $N$ должен быть достаточно маленьким, чтобы позволить нам рассмотреть множество тестов, несмотря на то, что наши решения медленные.

Сгенерировав $n$, мы генерируем массив $A$ с $n$ целыми числами от $0$ до $M$ и выводим его, чтобы по ходу бесконечного цикла мы всегда знали,
какой тест проходит сейчас. Это упростит нахождение ошибок в коде для генерации теста. Затем мы вызываем два алгоритма для $A$ и сравниваем результаты.
Если результаты отличаются, мы их печатаем и останавливаемся. В ином случае мы продолжаем цикл while.

Давайте запустим StressTest(10, 100'000) и скрестим пальцы в надежде, что он выдаст Wrong answer.
Для нас это выглядит как-то так (результат может отличаться на вашем компьютере из-за другого генератора случайных чисел).

...  
OK  
67232 68874 69499  
OK  
6132 56210 45236 95361 68380 16906 80495 95298  
OK  
62180 1856 89047 14251 8362 34171 93584 87362 83341 8784  
OK  
21468 16859 82178 70496 82939 44491  
OK 
68165 87637 74297 2904 32873 86010 87637 66131 82858 82935  
Wrong answer: 7680243769 7537658370  

Ура! Мы нашли пример, в котором MaxPairwiseProductNaive и MaxPairwiseProductFast приводят к разным результатам, и теперь можем проверить, что именно пошло не так.
Затем мы отлаживаем это решение через этот пример, находим баг, исправляем его и повторяем стресс-тестирование.

💡 Остановитесь и подумайте:
Видите что-то подозрительное в найденном наборе данных?

Обратите внимание, что генерировать тесты автоматически и проводить стресс-тестирование легко, но находить и исправлять баги — сложно.
Прежде чем углубиться в отладку багов, давайте попробуем сгенерировать тестовый пример поменьше — это упростит нам работу.
Для этого мы поменяем $N$ с 10 на 5 и $M$ с $100,000$ на $9$.

💡 Остановитесь и подумайте:
Почему мы сначала запустили StressTest с большими параметрами $N$ и $M$, а теперь хотим запустить с маленькими?

Затем мы заново начинаем стресс-тестирование и получаем следующее:

...  
7 3 6  
OK  
2 9 3 1 9  
2 3  
Wrong answer: 81 27  

Медленный алгоритм MaxPairwiseProductNaive даёт верный ответ $81$ ( $9 cdot 9 = 81$ ), но быстрый MaxPairwiseProductFast — неверный ($27$).

💡 Остановитесь и подумайте:
Как может выйти, что MaxPairwiseProductFast выдаёт $27$?

Чтобы избавиться от багов в первом решении, давайте проверим, какие два числа он считает наибольшими.
Для этого мы добавим следующую строку перед return в функции MaxPairwiseProductFast:

print(index_1, index_2)

Когда мы снова начинаем стресс-тестирование, мы получаем следующее:

...  
7 3 6  
OK  
2 9 3 1 9  
2 3  
Wrong answer: 81 27  

Обратите внимание, что наши решения работали и давали сбой на одних и тех же примерах тестирования, так как мы ничего не меняли в генераторе тестов.
Он использует псевдослучайные числа при создании тестов вместо действительно случайных.
Это значит, что последовательность выглядит случайной, но она одинакова каждый раз, когда работает программа.
Такое свойство удобно и важно. Советуем вам использовать эту практику, потому что в детерминированных программах (тех, что всегда выдают одинаковый результат при одинаковых вводных данных) легче находить баги, чем в недетерминированных.

Давайте теперь рассмотрим $index_1=2$ и $index_2=3$. Если мы обратим внимание на код для определения второго максимального числа, то заметим неочевидный баг.
Когда мы использовали условие для $i$ (число не должно быть таким же, как предыдущее самое большое), вместо сравнения $i$ и $index_1$ мы сравнили $A[i]$ и $A[index_1]$.
Это означает, что второе максимальное число отличается от первого по значению, а не по индексу элемента, который мы выбрали для решения задачи.
Так, наше решение не работает при любом тесте, в котором второе самое большое число равно первому.
Теперь изменим условие: вместо

A[i] != A[index_1]

мы используем

i != index_1

Проведя стресс-тестирование еще раз, мы видим на экране шквал сообщений OK. Ждём минуту, пока нам не надоест, и заключаем, что MaxPairwiseProductFast наконец-то работает правильно!

Однако не стоит останавливаться на этом, так как вы сгенерировали только очень маленькие тесты с $N=5$ и $M=10$.
Теперь нужно проверить, работает ли наша программа при большем $n$ и бо́льших элементах массива.
Таким образом, мы меняем $N$ на $1,000$ (при большем $N$ примитивное решение будет довольно медленным из-за квадратичного времени выполнения).
Мы также меняем $M$ на $200,000$ и запускаем программу.
Ещё раз наблюдаем, как экран заполняется сообщениями OK. Затем ждём минуту, а потом решаем, что MaxPairwiseProductFast действительно работает верно.
После этого мы сдаём получившееся решение системе оценки и успешно проходим тест!

Как вы можете заметить, даже при решении такой простой задачи как Максимальное попарное произведение сложно избежать
труднораспознаваемых ошибок на этапе проектирования и реализации алгоритма. Приведённый ниже псевдокод — это пример более надежного способа реализации алгоритма.

MaxPairwiseProductFast(A[1..n]):
    index = 1
    for i from 2 to n
        if A[i] > A[index]:
            index = i
    swap(A[index], A[n]) // поставим наибольшее значение в конец массива
    index = 1:
    for i from 2 to n - 1
        if A[i] > A[index]:
            index = i
    swap(A[index], A[n - 1]) // поставим второй по величине элемент предпоследним
    return A[n - 1] * A[n]

В этой книге вы узнаете, как проектировать и реализовывать алгоритмы так, чтобы минимизировать вероятность ошибок. А заодно научитесь тестировать вашу реализацию.

Ещё более быстрый алгоритм

Алгоритм MaxPairwiseProductFast находит два самых больших числа примерно за $2n$ сравнений.

💡 Остановитесь и подумайте:
Найдите два самых больших элемента в массиве за $1.5n$ сравнений.

Когда вы решите эту задачу, вас ждет ещё более сложное упражнение. Попробуйте с ним справиться!

💡 Остановитесь и подумайте:
Найдите два самых наибольших элемента в массиве за $n + lceil log_2 n rceil – 2$ сравнений.

Если это упражнение показалось вам слишком простым, посмотрите задачи ниже. Они вполне могут оказаться на следующем собеседовании!

✒️ Упражнение:
Докажите, что не существует алгоритма, которому потребуется менее $n + lceil log_2 n rceil – 2$ сравнений, чтобы найти два самых больших элемента массива.

✒️ Упражнение:
Какой алгоритм найдёт три самых больших элемента быстрее всего?

Более компактный алгоритм

Задачу Максимальное попарное произведение можно решить с помощью следующего компактного алгоритма, который использует сортировку (в неубывающем порядке).

MaxPairwiseProductBySorting(A[1..n]):
    Sort(A)
    return A[n-1]*A[n]

Этот алгоритм делает даже больше, чем нам нужно: вместо того, чтобы найти два самых больших элемента, он сортирует весь массив.
Поэтому его время выполнения $O(nlog n)$, а не $O(n)$. Однако для таких ограничений ($2 le n le 2 cdot 10^5$) он достаточно быстрый, чтобы выполнить задачу за секунду и успешно пройти тесты в нашей систему оценки.

Формулировка задачи:

дана последовательность целых положительных чисел. найти произведение только тех чисел, которые больше заданного числа М. если таких нет, то выдать сообщение об этом.

Код к задаче: «Найти произведение только тех чисел, которые больше заданного числа»

textual

Листинг программы

program bb;
uses crt;
const n=10;
var a:array[1..10]of integer;
i,m,p:integer;
begin
randomize;
for i:=1 to n do
begin
write('a[',i,'] =');
read(a[i]);
end;
writeln;
write('Ââåäèòå M = ');
read(m);
writeln;
p:=1;
for i:=1 to n do
if a[i]>m then
begin
p:=p*a[i];
end;
if p<>1 then
write('p = ',p)
else
write('Г’Г*ГЄГЁГµ Г·ГЁГ±ГҐГ« Г*ГҐГІ');
end.

Вам на вход подается N целых чисел. Вам необходимо будет найти среди них два числа, которые дают максимальное произведение. Ответом на задачу будет произведение этих чисел. Массивы использовать в данной задаче запрещено!

Ввод: На первой строке вводится натуральное N, 2 ≤ N ≤ 10000. На последующих N строках вводятся целые числа |ai| ≤ 10000.

Формат вывода: Одно число — максимальное произведение двух чисел.

Попытка найти максимальное и идущее за ним максимальное и умножить их не дает нужный результат, не учитывается одинаковые значения и минусовые значения.

n = int(input())
max1 = 0
max2 = 0
if 2 <= n <= 10000:       #
    lst = list(int(input()) for i in range(n))
    for f in lst:
        if f > max1:
            max1 = f
    for j in lst:
        if j > max2 and j < max1:
            max2 = j
max = max1 * max2
print(max)

Kromster's user avatar

Kromster

13.5k12 золотых знаков43 серебряных знака72 бронзовых знака

задан 1 сен 2022 в 10:00

b8free's user avatar

8

Ну в общем, нечто подобное и надо делать. Только нужно поддерживать две пары – наибольших положительных и наименьших отрицательных

Рабочий код:

max1 = 0
max2 = 0
min1 = 0
min2 = 0
n = int(input())
for _ in range(n):
    f = int(input())
    if f > 0:
        if f > max1:
            max2 = max1
            max1 = f
        elif f > max2:
            max2 = f
    elif f < 0:
        if f < min1:
            min2 = min1
            min1 = f
        elif f < min2:
            min2 = f
mx = max(max1 * max2, min1 * min2, max1 * min1)
print(mx)

ответ дан 1 сен 2022 в 10:09

MBo's user avatar

MBoMBo

47.8k1 золотой знак17 серебряных знаков40 бронзовых знаков

6

Только изучаю Python, ваша задачка заинтересовала ради тренировки. Вот мое решение без массивов (списков, кортежей, множеств, словарей). Насколько я могу судить, задачу выполняет.

'''
Вам на вход подается N целых чисел. Вам необходимо будет найти 
среди них два числа, которые дают максимальное произведение. 
Ответом на задачу будет произведение этих чисел. Массивы 
использовать в данной задаче запрещено!
'''

vmax = False
vmin = False
multiply = False

while True:
    i = input("Введите цифру или 'q' для завершения: ")

    if i == 'q':
        break

    try:
        i = int(i)
    except (TypeError, ValueError):
        print("ERROR! Нужно вводить цифры или 'q' для завершения")
        continue

    if vmax == False and 2 <= i <= 10000:
        # при первом вводе значения оно должно быть между 2 <= N <= 10000
        # учитывая это, можно спокойно оперировать стартом программы при vmax = 0
        vmax = i
        vmin = i
    elif vmax != False and i <= 10000:
        # при втором и далее вводе значений они должны быть <= 10000
        m = i * vmax
        n = i * vmin

        multiply = max(multiply, m, n)

        # if multiply == False:
        #     if m > n:
        #         multiply = m
        #     else:
        #         multiply = n
        # else:
        #     if m > multiply:
        #         multiply = m
        #     elif n > multiply:
        #         multiply = n

        if i > vmax:
            vmax = i

        if i < vmin:
            vmin = i
    else:
        print('ERROR! Нужно вводить цифры 2 <= N <= 10000 для первого значения и <= 10000 для последующих')

print('answer: %d' % multiply)

ответ дан 1 сен 2022 в 11:59

Firsov36's user avatar

Firsov36Firsov36

9161 золотой знак4 серебряных знака12 бронзовых знаков

6

Последние несколько задач показывали, что Python удобнее С++, но в этой задаче всё наоборот. Давайте посмотрим.

Условие задачи с сайта acmp.ru
Условие задачи с сайта acmp.ru

Если никакие мысли по поводу решения задачи не приходят в голову, то всегда можно написать самое простое решение и позапускать его на разных входных данных. Часто после такого можно найти закономерности или способы сокращения времени работы. В этой задаче можно было бы написать три вложенных цикла и находить максимум.

Можно пойти другим путём. Что было бы, если бы все числа были натуральными? Разумно предположить, что тогда максимальное произведение дали бы три самых больших числа. Супер! Мы уже близки к решению задачи.

Что же меняется, когда появляются отрицательные числа? Лишь то, что произведение двух отрицательных чисел даёт положительное число. То есть, если взять два самых маленьких числа, то произведение может получиться больше, чем у двух самых больших. И всё? Да. А если все числа будут отрицательными? Тогда произведение трёх чисел в любом случае будет отрицательным, а это значит, что нам надо выбрать минимальное по модулю, это можно получить минимальными по модулю множителями (то есть самыми большими из имеющихся чисел).

А в чём же тогда сложность задачи? В размере входных данных. Нам даётся до миллиона чисел. То есть входной файл может быть до 8Мб (7 цифр в числе, знак минус и пробел). И это создаёт две проблемы: объём используемой памяти и время считывания такого количества данных.

Если на Python’е использовать простой список или кортеж, и даже если посылать решение на PyPy, то пройти ограничение по памяти очень сложно. На странице лучших попыток видно, что только 4 человек смогли это сделать. В то время как на С++ можно либо использовать scanf, либо известную каждому олимпиадному программисту на С++ “магическую строку”:

Ускорение потокового ввода на С++
Ускорение потокового ввода на С++

После такого можно вообще не заботиться о скорости в этой задаче, и даже не обращать внимание на асимптотику решения и использовать сортировку:

Полное решение на С++
Полное решение на С++

Главное не забывайте про переполнение типов. Здесь у нас сами числа до 30000, но их произведение уже не помещается в тип int, поэтому в произведении добавлен множитель 1LL (единица типа long long), и тогда компилятор всё произведение считает в типе данных long long.

Конечно же, использование сортировки для поиска трёх максимальных чисел – это излишество, и правильнее находить их за один проход по массиву. Хммм… один проход, а это значит, что нам не надо хранить все данные в оперативной памяти.

Заведём переменные для всех необходимых нам значений:

Объявление переменных для трёх максимальных и двух минимальных значений
Объявление переменных для трёх максимальных и двух минимальных значений

И будем считывать и сразу обрабатывать входные данные:

Считывание данных
Считывание данных

Как же найти три максимальных числа? Элементарно. Мы поддерживанием ТОП-3. Если встретили число, которое больше текущего максимума, то тогда обновится весь топ. Но нельзя забывать, что число может быть меньше максимального, но превышать второй (или третий) максимум, тогда обновится соответствующая часть топа.

Поиск трёх максимальных чисел
Поиск трёх максимальных чисел

Аналогично поступаем с поиском двух минимальных чисел:

Поиск двух минимальных чисел
Поиск двух минимальных чисел

Ну, а вычисление итогового ответа остаётся почти без изменений:

Вычисление и вывод ответа
Вычисление и вывод ответа

Если отправить оба решения, то мы увидим сильное уменьшение использованной памяти, и это понятно, потому что теперь мы не храним все числа одновременно. Но вот время работы уменьшилось не очень сильно, потому что при таком размере входных данных основные его расходы именно на считывании:

Результаты работы обоих решений
Результаты работы обоих решений

Сила С++ в его скорости. А если вам удалось сдать задачу на Python, то поделитесь секретом в комментариях, всем будет интересно.

Предыдущий выпуск: Задача 131. Перепись

Я очень хочу, чтобы мои советы были полезны вам, а для того, чтобы быстрее всех получать новые статьи можно подписаться на мой канал.

Добавить комментарий