Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.63/140: Рейтинг темы: голосов - 140, средняя оценка - 4.63
0 / 0 / 0
Регистрация: 25.07.2018
Сообщений: 31

Калькулятор с восстановлением ответа

16.11.2018, 22:18. Показов 28316. Ответов 10

Студворк — интернет-сервис помощи студентам
есть задача:
Имеется калькулятор, который выполняет три операции:

Прибавить к числу X единицу.
Умножить число X на 2.
Умножить число X на 3.
Определите кратчайшую последовательность операций, необходимую для получения из числа 1 заданное число N.

Входные данные
Программа получает на вход одно число N, не превосходящее 106.

Выходные данные
Выведите строку, состоящую из цифр "1", "2" или "3", обозначающих одну из трех указанных операций, которая получает из числа 1 число N за минимальное число операций. Если возможных минимальных решений несколько, выведите любое из них. 😁

Пример

Ввод Вывод
1

5
121
562340
3333312222122213312


В сети много решений, но я не могу понять как они работают. Можете пожалуйста объяснить как работает алгоритм этой задачи и как можно решать подобные.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.11.2018, 22:18
Ответы с готовыми решениями:

наибольшая общая подпоследовательность с восстановлением ответа
#include <bits/stdc++.h> using namespace std; int main() { ios_base::sync_with_stdio(0); int n, m; cin >> n; ...

Наибольшая общая подпоследовательность с восстановлением ответа
Даны две последовательности, требуется найти и вывести их наибольшую общую подпоследовательность. Формат входных данных В первой...

Калькулятор с восстановлением ответа
Ограничение по времени работы программы: 5 секунд Эта задача аналогична предыдущей задаче «Калькулятор», но в этой задаче требуется также...

10
490 / 286 / 129
Регистрация: 30.10.2018
Сообщений: 1,309
16.11.2018, 22:26
EVGENNIY1337, скорее всего тут просто нужно посчитать сколько операция выполнет каждое дествия по отдельности, к примеру циклом.

Но можно конечно же схитрить, и сделать что-то типо:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int First = N - 1, Second, Third;
 
int temp = 1;
for(int  i = 1 ; temp < N; i++)
{
    temp *= 2;
if(temp == N)
   Second = i;
}//если Second так и не будет инициализировано то умножениям на два нельзя, идентично с тройкой
temp = 1;
for(int  i = 1 ; temp < N; i++)
{
    temp *= 3;
if(temp == N)
   Third= i;
}
0
0 / 0 / 0
Регистрация: 25.07.2018
Сообщений: 31
16.11.2018, 22:43  [ТС]
здесь надо показать в какой последовательности будут происходить операции, и я никак не могу понять, как определить, что нужно сделать, прибавить единицу? умножить на 2? умножить на 3?!
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
16.11.2018, 23:22
Цитата Сообщение от EVGENNIY1337 Посмотреть сообщение
я не могу понять как они работают
Скорее всего они основаны на принципе динамического программирования. Просто применяешь его для рекурсивной формулы, которая очевидным образом получается для твоей задачи:
https://www.cyberforum.ru/cgi-bin/latex.cgi?f(n)=\min(f'(n, 2), f'(n, 3), f(n-1)), где https://www.cyberforum.ru/cgi-bin/latex.cgi?f'(n, m)=\begin{cases}<br />
f(n/m) & \text{ if } n \text{ mod } m = 0 \\ <br />
+\infty & \text{ otherwise}  <br />
\end{cases}

Добавлено через 7 минут
а само https://www.cyberforum.ru/cgi-bin/latex.cgi?f(n) - минимальное число операций для получения числа https://www.cyberforum.ru/cgi-bin/latex.cgi?n
0
0 / 0 / 0
Регистрация: 25.07.2018
Сообщений: 31
16.11.2018, 23:39  [ТС]
я не понимаю, что означает +∞ и как вывести именно какие операции применяются
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
17.11.2018, 00:32
Лучший ответ Сообщение было отмечено EVGENNIY1337 как решение

Решение

Цитата Сообщение от EVGENNIY1337 Посмотреть сообщение
что означает +∞
Бесконечность. Вся суть функции https://www.cyberforum.ru/cgi-bin/latex.cgi?f'(n,m) - исключить из рассмотрения те числа https://www.cyberforum.ru/cgi-bin/latex.cgi?n, которые не делятся на https://www.cyberforum.ru/cgi-bin/latex.cgi?m (т.е. в твоем случае 2 или 3).

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

А так, идея следующая. Создаешь массив https://www.cyberforum.ru/cgi-bin/latex.cgi?a длины https://www.cyberforum.ru/cgi-bin/latex.cgi?n, где каждый элемент https://www.cyberforum.ru/cgi-bin/latex.cgi?a_i - минимальное количество операций для получения числа https://www.cyberforum.ru/cgi-bin/latex.cgi?i. Очевидно, что https://www.cyberforum.ru/cgi-bin/latex.cgi?a_1=0. Рассматривать https://www.cyberforum.ru/cgi-bin/latex.cgi?a_2=1,a_3=1,a_4=2,a_5=3 не интересно, так что сразу перескочим к https://www.cyberforum.ru/cgi-bin/latex.cgi?a_6.
Число 6 можно получить тремя способами: умножив какое-то число на 2, умножив какое-то число на 3, и прибавив к какому-то числу 1. Если бы мы воспользовались первым способом, но для получения числа 6 потребовалось бы https://www.cyberforum.ru/cgi-bin/latex.cgi?a_3 + 1 операций, если вторым способом - https://www.cyberforum.ru/cgi-bin/latex.cgi?a_2 + 1 операция, третьим - https://www.cyberforum.ru/cgi-bin/latex.cgi?a_5 + 1. Так как нас интересует минимальное количество операций, то выбираем самое маленькое значение из получившихся https://www.cyberforum.ru/cgi-bin/latex.cgi?a_6=2. С https://www.cyberforum.ru/cgi-bin/latex.cgi?a_7 все еще проще, оно могло получиться только прибавлением единицы, т.е. https://www.cyberforum.ru/cgi-bin/latex.cgi?a_7=a_6+1.

Данная процедура повторяется, пока мы не дойдем до https://www.cyberforum.ru/cgi-bin/latex.cgi?a_n. Для восстановления последовательности операций нужно просмотреть ранее вычисленные значения. Если https://www.cyberforum.ru/cgi-bin/latex.cgi?a_n=k, то число https://www.cyberforum.ru/cgi-bin/latex.cgi?n было получено из числа https://www.cyberforum.ru/cgi-bin/latex.cgi?m\in \{n/2,n/3,n-1\} для которого https://www.cyberforum.ru/cgi-bin/latex.cgi?a_m=k-1 и т.д.
1
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,536
Записей в блоге: 1
17.11.2018, 03:00
Лучший ответ Сообщение было отмечено EVGENNIY1337 как решение

Решение

Цитата Сообщение от EVGENNIY1337 Посмотреть сообщение
Программа получает на вход одно число N, не превосходящее 106.
Цитата Сообщение от EVGENNIY1337 Посмотреть сообщение
562340
3333312222122213312
теги, блджад! теги!

Добавлено через 16 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<iostream>
struct op {
    unsigned count_op;
    unsigned code_op;
    unsigned operand;
}x[1000001];
void print(int operand) {
    if (operand != 1) {
        print(x[operand].operand);
        std::cout << x[operand].code_op;
    }
}
int main()
{
    int N;
    std::cin >> N;
    memset(x, 0xFF, (N+1) * sizeof(op));
    x[1] = { 0 };
    for (int i = 1; i < N; ++i)
    {
        if (x[i + 1].count_op > x[i].count_op + 1)
        {
            x[i + 1].count_op = x[i].count_op + 1;
            x[i + 1].code_op = 1;
            x[i + 1].operand = i;
        }
        if (i*2<=N && x[i*2].count_op > x[i].count_op+1)
        {
            x[i * 2].count_op = x[i].count_op+1;
            x[i * 2].code_op = 2;
            x[i * 2].operand = i;
        }
        if (i * 3 <= N && x[i * 3].count_op > x[i].count_op + 1)
        {
            x[i * 3].count_op = x[i].count_op + 1;
            x[i * 3].code_op = 3;
            x[i * 3].operand = i;
        }
    }
    print(N);
    std::cout << std::endl << ((((1 * 3 * 3 * 3 * 3 * 3 + 1) * 2 * 3 * 3 + 1) * 2 * 2 + 1) * 2 * 2 * 2 + 1) * 2 * 2;
    //даёт разные ответы в сравнении с примером 562340, но оба минимальной длины
    std::cout << std::endl << ((((1 * 3 * 3 * 3 * 3 * 3 + 1) * 2 * 2 * 2 * 2 + 1) * 2 * 2 * 2 + 1) * 3 * 3 + 1) * 2;
    return 0;
}
1
0 / 0 / 0
Регистрация: 25.07.2018
Сообщений: 31
17.11.2018, 16:59  [ТС]
я новичок в программировании. можете пояснить что означает "memset(x, 0xFF, (N+1) * sizeof(op));"
и ".count_op" ".code_op" ".operand"
0
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,536
Записей в блоге: 1
17.11.2018, 17:11
EVGENNIY1337, а всё остальное понятно что ли? Ну то есть самого главного вопроса, "что это за массив такой" и "почему его индексы умножаются" у тебя не возникло?

Если ты новичок, не знакомый со структурами, то... ну чисто гипотетически можно и без структур подобные этой олимпиадные задачи решать... но зачем?
У тебя жуткие пробелы в знаниях, а ты лезешь в олимпиады по программированию!
0
0 / 0 / 0
Регистрация: 25.07.2018
Сообщений: 31
17.11.2018, 17:17  [ТС]
преступил я к олимпиадному программированию недавно, и структуры мне ещё не требовались, теперь я знаю, что есть такие инструменты, да и что же надо в олимпиадном программировании на начальном уровне? мне кажется не так-то много.
0
0 / 0 / 0
Регистрация: 14.02.2021
Сообщений: 2
23.10.2021, 13:02
Цитата Сообщение от EVGENNIY1337 Посмотреть сообщение
Можете пожалуйста объяснить как работает алгоритм этой задачи и как можно решать подобные.
просто создаем 2 вектора - предки и вектор количества операций, необходимых для получения числа
обновляем предка, когда обновляем количество операций
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
#include <math.h>
using namespace std;
 
vector<int> dp;
vector<int> p;
int e(int a, int b){
    if (a == 0){
        return b;
    }
    return e(b % a, a);
}
 
 
int main(){
    int n;
    cin >> n;
    if (n <= 1){
        return 0;
    }
    dp.resize(7 * n);
    p.resize(7 * n);
    dp[1] = 0;
    for (int i = 1; i <= n + 1; ++i){
        if (dp[i + 1] == 0 || dp[i + 1] > dp[i]){
            dp[i + 1] = dp[i] + 1;
            p[i + 1] = 1;
        }
        if (dp[i * 2] == 0 || dp[i * 2] > dp[i]){
            dp[i * 2] = dp[i] + 1;
            p[i * 2] = 2;
        }
        if (dp[i * 3] == 0 || dp[i * 3] > dp[i]){
            dp[i * 3] = dp[i] + 1;
            p[i * 3] = 3;
        }
    }
    vector<int> ans;
    while (n > 1){
        if (p[n] == 1){
            ans.push_back(1);
            n -= 1;
        } else if (p[n] == 2){
            ans.push_back(2);
            n /= 2;
        } else {
            ans.push_back(3);
            n /= 3;
        }
    }
    for (int i = ans.size() - 1; i >= 0; --i){
        if (ans[i] != 0){
            cout << ans[i];
        }
    }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.10.2021, 13:02
Помогаю со студенческими работами здесь

Калькулятор с восстановлением ответа (Python)
Здравствуйте. В общем, условие такое: *** Исполнитель «Калькулятор» может с заданным числом X выполнить одну из трех операций и ...

Динамическое программирование задача "Калькулятор с восстановлением ответа" (Pascal ABC)
Всем привет. Пишу с проблемой о принятии моей задачи тестирующей программой. Сама задача: Имеется калькулятор, который выполняет три...

Калькулятор: вывод ответа на форму html
Здравствуйте, помогите. Написал калькулятор в одном файле test.php, все работает норм , а мне надо, чтобы в html файле, была форма и...

Калькулятор: вывод ответа, запоминание числа
Пробую написать калькулятор(основываясь на статьи в сети) столкнулся с проблемами:вывод ответа, запоминание числа. ПОМОГИТЕ ПЛИИИЗЗЗ!!

Калькулятор (ввод числа, +, -, *, /, ^, второе число, вывод ответа)
Создайте калькулятор, который принимает число, базовый математический оператор (+, -, *, /, ^) и второе число из пользовательского ввода, и...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru