@impelix

Что можно убрать чтобы оптимизировать затраты памяти?

Задача кода сложить 2 числа которые заданы в формате: Сначала идет кол-во цепочек повторяющихся цифр, потом количество цифр идущих подряд, а потом сама цифра. Например: число 111 - это 1 3 1, а число 21 это 2 1 2 1 1. Задча сложить 2 числа которые задаются таким способом и вывести ответ в таком же формате.
Вроде как длинная арифметика работает правильно, но теперь он не заходит по памяти, насколько я понимаю есть какой-то другой, альтернативный вариант решения подобных задач. Насчет того, какое из чисел больше, то 1 всегда больше, поэтому запись ответа в него подойдет.
КОД
#include <iostream>
#include <vector>
#include <algorithm>

struct vv{
    int c, num;
};

// Функция для вывода большого числа
void printBigNumber(const std::vector<int>& number) {
    int cnt = 0;
    std::vector<vv> kk;
    for (int k = 0; k < number.size(); ++k) {
        if (k + 1 < number.size()) {
            if (number[k] == number[k + 1]) {
                cnt++;
            } else {
                kk.push_back({cnt + 1, number[k]});
                cnt = 0;
            }
        } else {
            kk.push_back({cnt + 1, number[k]});
        }
    }
    std::cout << kk.size() << std::endl;
    for (auto j: kk) {
        std::cout << j.c << ' ' << j.num << '\n';
//    }
//    for(auto k : number){
//        std::cout << k;
//    }
    }
}
void add(std::vector<int>& num1, std::vector<int>& num2) {
    int size1 = num1.size();
    int size2 = num2.size();
    int carry = 0;
    int maxSize = std::max(size1, size2);

    for (int i = 0; i < maxSize; i++) {
        int digit1 = (i < size1) ? num1[size1 - i - 1] : 0;
        int digit2 = (i < size2) ? num2[size2 - i - 1] : 0;

        int sum = digit1 + digit2 + carry;
        carry = sum / 10;
        num1[size1 - i - 1] = sum % 10;
    }

    if (carry > 0) {
        num1.insert(num1.begin(), carry);
    }
}

int main() {
    int n;
    std::vector<int> num1;
    std::vector<int> num2;
    std::cin >> n;
    for (int i = 0; i < n; ++i) {
        int q;
        int num;
        std::cin >> q >> num;
        for (int j = 0; j < q; ++j) {
            num1.push_back(num);
        }
    }
    std::cin >> n;
    for (int i = 0; i < n; ++i) {
        int q;
        int num;
        std::cin >> q >> num;
        for (int j = 0; j < q; ++j) {
            num2.push_back(num);
        }
    }
    add(num1, num2);
    printBigNumber(num1);
}
  • Вопрос задан
  • 158 просмотров
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
(Отредактировал ответ согласно комментариям). Как выяснилось, в задаче длины вот групп одинаковых цифр могут достигать 10^18. Поэтому попытка развернуть эту запись обречена на провал: все эти цифры потребуют миллионов террабайт. Естественно, ваша программа падает еще на этапе ввода ( а еще, вы там читаете int, в который такие большие числа не влезают, что будет дополнительной ошибкой).

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

Главная часть решения - это научиться складывать две группы цифр равной длины (плюс перенос). Вроде 7777 + 4444 +1 = 12222 - 4 двойки и 1 единица (помните, порядок у нас развернутый же). Тут можно всегда выделять в отдельную группу первую цифру из-за переноса. Отдельный случай будет, похоже, если цифры дают в сумме 9 и есть перенос (10000..000). А иначе вы получите что-то вида abbbbbbc в оставшихся цифрах. Главное, что при сумме нельзя группы распаковывать.

В конце разверните группы и объедините подряд идущие группы для одинаковых цифр.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы