LINUX.ORG.RU

Задача «Число операций»

 


0

1

Дано целое неотрицательное число. С ним можно делать следующие операции: увеличивать на 1; уменьшать на 1; делить его на два, если оно четное. Требуется за минимальное число операций получить 0. Вход. Целое неотрицательное число меньше 2000000.

Выход. Минимальное число операций.

http://www.kml.mipt.ru/judge/problems.pl?problem=026

#include <iostream>

using namespace std;

int main() {
    int N, answer = 0;
    cin >> N;
    while(N != 0) {
         if(N%2){
              if( (N+1) % 4){
                   N--;
              }
              else
                  N++;
         }
         else
             N /=2;
         answer++;
    }
    cout << answer << endl;
}

Где ошибка?



Последнее исправление: cetjs2 (всего исправлений: 1)
Ответ на: комментарий от emulek

Если число четное - делим на два.

Если число нечетное и при прибавлении 1 делится на четыре - прибавляем 1.

Иначе отнимаем 1.

AIv ★★★★★
()
Ответ на: комментарий от AIv

Если число нечетное и при прибавлении 1 делится на четыре - прибавляем 1.

и смысл? Ведь после прибавления 1 нам придётся два раза делить на 2. Или в условии разрешено делить на 4? Я что-то этого не наблюдаю.

И даже если и наблюдаю, то что ты скажешь про цену операции если число+1 делится на 4? Она по твоему бесплатная?

А мне вот кажется, что на amd64 быстрее будет моим методом пользоваться, и делить на 2 даже тогда, когда можно делить на 4. Ибо цена лишнего сдвига куда меньше, чем цена лишней проверки &3 и плюс цена условного перехода.

emulek
()
Ответ на: комментарий от emulek

В задаче ТС ни слова не сказано о том, что проверки условий и пр. считаются операциями. Можно считать, что преобразования числа просто модель для какого то достаточно дорого процесса.

И всегда лучше два раза поделить на два, если есть возможность. Иначе представьте, как адово будет выглядеть цепочка для 2^n-1 ;-)

AIv ★★★★★
()
Ответ на: комментарий от AIv

В задаче ТС ни слова не сказано о том, что проверки условий и пр. считаются операциями.

вот потому-то и ВУЗы выпускают говнокодеров, которые считают инкремент — операцией, а вот «поделить на 4 с остатком, и проверить равенства остатка 3» — «не операцией».

В таком случае я могу и такой алгоритм написать, с НУЛЁМ операций:

проверить и запомнить ВСЕ варианты
выбрать самый короткий вариант
распечатать число операций для самого короткого варианта

разве в этом «алгоритме» есть хоть одна операция?

Можно считать, что преобразования числа просто модель для какого то достаточно дорого процесса.

нельзя. Потому-что в твоих «проверках» неявно сами числа используются. Т.е. если у тебя операции дорогие, то и проверки будут такими же.

И всегда лучше два раза поделить на два, если есть возможность. Иначе представьте, как адово будет выглядеть цепочка для 2^n-1

мне это только-что продемонстрировали. При этом сами проверки конечно были «спрятаны», код аффтор предоставить постеснялся.

emulek
()
Ответ на: комментарий от emulek

вот потому-то и ВУЗы выпускают говнокодеров

Человеку, который полагает, что

Можно считать, что преобразования числа просто модель для какого то достаточно дорого процесса.

нельзя. Потому-что в твоих «проверках» неявно сами числа используются. Т.е. если у тебя операции дорогие, то и проверки будут такими же.

слово «говнокодер» надо исключить из лексикона, чаще смотреться в зеркало и работать над уменьшением ЧСВ.

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

Это типичная задача на оптимизацию, я сам такие решаю эпизодически. При этом оптимизировать сам алгоритм (менять там % на & и / на >>) никакого смысла нет, задача не в этом состоит. Все равно преобразование самих данных занимает горааааздо больше времени.

AIv ★★★★★
()
Ответ на: комментарий от IvS

Согласен;-)

Ну тогда тут надо пытаться проанализировать все пути... или систему пенальти вводить.

Можно наверное написать целевую функцию, которая будет показывать сколько инкрементов имеет смысл применять.

AIv ★★★★★
()
Ответ на: комментарий от IvS

А нет, не согласен, все работает.

Неважно когда инкрементить - до деления, или после. Т.е. для 1022 получается 12 итераций, что так, что так.

AIv ★★★★★
()
Ответ на: комментарий от AIv

Т.е. для 1022 получается 12 итераций, что так, что так.

Нет, добавлять два раза даёт лишнюю операцию. См. выше.

redgremlin ★★★★★
()
Ответ на: комментарий от AIv

дак тут же List! к тому же можно ввести свой AscList с автоматической корректностью, но тут уже лучше агду брать. ну и плюс всякие оптимизации типа добавления (next_power_of_2 n, next_power_of_2 n - n, «+») и удаления уже посещённых точек.

qnikst ★★★★★
()
Ответ на: комментарий от AIv

Можно наверное написать целевую функцию, которая будет показывать сколько инкрементов имеет смысл применять.

инкрементов нужно применять ровно столько, сколько есть в числе 111 (т.е. три бита подряд равные 1). Каждая такая тройка даёт профит 1 операцию, или больше, если это не тройка, а четвёрка и т.п.

emulek
()
Ответ на: комментарий от qnikst

добавляем в дерево поиска

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

emulek
()
Ответ на: комментарий от emulek

мой алгоритм решает задачу всегда, твой нет, что ещё дальше говорить то... очень грубо оценивая для 2^n последовательных чисел твой её решает в sum_1^n n+1, итого: (n+1)(n+2)/2.

Я нигде не ошибся?

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

мой алгоритм решает задачу всегда, твой нет

твой использует недопустимую операцию. Точнее неопределённую.

очень грубо оценивая для 2^n последовательных чисел твой её решает в sum_1^n n+1, итого: (n+1)(n+2)/2. Я нигде не ошибся?

ошибся. Я уже говорил: log2(n) делений и log2(n)/2 вычитаний. А твой решает иногда да, лучше, но применяет ещё и log2(n) операций n%4. ИЧСХ, ты эту операцию не сможешь отложить своей монадой, потому-что тебе её надо проводить ДО принятия решения, инкремент тебе делать, или декремент. Можешь конечно попробовать и так и так сделать, но это уже не 2 деления на 2 итерации, а 4 деления на две итерации. Плюс ещё 2 или 3 деления придётся сделать.

emulek
()
Ответ на: комментарий от emulek

твой использует недопустимую операцию. Точнее неопределённую.

Ты не можешь отличить решение и процесс получения решения. К сожалению даже резиновая уточка стоящая на моём столе более хороший программист чем ты.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Девочки, не ссорьтесь! Тем более, не надо бить школьника... он просто маленький и многого не знает, но он обязательно вырастет и напишет новое ядро линукса;-))))

AIv ★★★★★
()
Ответ на: комментарий от qnikst

Ты не можешь отличить решение и процесс получения решения.

дык разве в этой задачке требуется дать 200000 решений, для каждого числа свою строчку с ++,--,/2 ?

А... А я думал, написать программу надо...

К сожалению даже резиновая уточка стоящая на моём столе более хороший программист чем ты.

ну куда мне до твоей уточки...

emulek
()
Ответ на: комментарий от AIv

Надо ему как то объяснить что Бетховен

какая попсня...

emulek
()
Ответ на: комментарий от emulek

А... А я думал, написать программу надо...

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

ну куда мне до твоей уточки...

я рад, что и ты признал это.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

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

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

emulek
()
Ответ на: комментарий от emulek

да, я увидел твою логику.. в общем-то формально задачу можно трактовать таким образом, но тогда она не несёт никакого смысла, т.к. превращается в элементарную для всех.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

в общем-то формально задачу можно трактовать таким образом

ох... Ну наконец-то.

но тогда она не несёт никакого смысла, т.к. превращается в элементарную для всех.

она и в вашем списочном смысле не слишком сложна.

emulek
()
Ответ на: комментарий от emulek

она и в вашем списочном смысле не слишком сложна.

в этом случае она не решается устно, или решается, но не очевидно, во всяком случае, что попрограммировать есть.

P.S. мне действительно интересно существуют ли случаи, когда плюс может быть в середине операции, поидее должны существовать, но придумать пример мне не удалось.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

P.S. мне действительно интересно существуют ли случаи, когда плюс может быть в середине операции, поидее должны существовать, но придумать пример мне не удалось.

В смысле? 11100? /2/2+1/2/2/2-1?

Waterlaz ★★★★★
()
Ответ на: комментарий от Waterlaz

Точнее даже

echo 0

sh в /bin/sh у меня, но его моно и не указывать;-)

AIv ★★★★★
()
Ответ на: комментарий от qnikst

P.S. мне действительно интересно существуют ли случаи, когда плюс может быть в середине операции, поидее должны существовать, но придумать пример мне не удалось.

? Для любого N = 2^k(2^l-1) будет { /2 × k, +, /2 × l }

redgremlin ★★★★★
()
Ответ на: комментарий от AIv

не подходит же, ему нужно написать решение на ассемлберноподобном языке, где типы это Int и есть операции:

PLUS     %reg       -- +1
MINUS    %reg       -- -1
MOD2     %ref %addr -- /2 или прыжок на %addr если деление невозможно
ISZERO   %reg %addr1 %addr2 -- в зависимости от результата прыжок на addr1 или addr2
EXIT     -- выход

+ всякие операции типа положить в регистр и т.п.

и какая-то программа вида

 
10: ISZERO %a 20 100
20: MOD2  %a 30
30: MINUS %a
40: GOTO 10
100: EXIT

qnikst ★★★★★
()
Ответ на: комментарий от AIv

все правильно сказал.

Меня другое умиляет, почему в задаче ТС проверки в условиях не считаются операциями?;-)

тебе тоже стоит уменьшить свое чсв и взглянуть внимательней на код.

Забавный тред: тс нужно было подсказать про n==3, предложить более оптимизированный вариант, спасибо MKuznetsov. Но тред скатился в срач не только из-за непонимая сути acm, но и не умения правильно читать корявые тексты.

Ждем новых задачек от ТС и бурных обсуждений.

parrto
()
Ответ на: комментарий от qnikst

ему нужно написать решение на ассемлберноподобном языке

Их есть у меня!

        .file   "test.cpp"
        .section        .rodata.str1.1,"aMS",@progbits,1
.LC0:
        .string "0"
        .section        .text.startup,"ax",@progbits
        .p2align 4,,15
        .globl  main
        .type   main, @function
main:
.LFB12:
        .cfi_startproc
        subq    $8, %rsp
        .cfi_def_cfa_offset 16
        movl    $.LC0, %edi
        call    puts
        xorl    %eax, %eax
        addq    $8, %rsp
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc
.LFE12:
        .size   main, .-main
        .ident  "GCC: (Debian 4.7.2-5) 4.7.2"
        .section        .note.GNU-stack,"",@progbits

AIv ★★★★★
()
Ответ на: комментарий от parrto

тебе тоже стоит уменьшить свое чсв и взглянуть внимательней на код.

Для просмотра мне хватает кода от своих студентов.

AIv ★★★★★
()
Ответ на: комментарий от qnikst

в этом случае она не решается устно, или решается, но не очевидно, во всяком случае, что попрограммировать есть.

ИМХО решение очевидно...

мне действительно интересно существуют ли случаи, когда плюс может быть в середине операции, поидее должны существовать, но придумать пример мне не удалось.

14 попробуй. Это чётное. Минимальное нечётное очевидно 29.

29-1=28
28/2=14
14/2=7
7+1=8
8/2=4
4/2=2
2/2=1
1-1=0
это так, с ходу. Но вроде меньше быть не может.

emulek
()
Ответ на: комментарий от AIv

таких операций не определено в условии. Продолжаем клоунаду?

emulek
()
Ответ на: комментарий от parrto

Я не пишу на асме, g++ это делает лучше меня.

AIv ★★★★★
()
Ответ на: комментарий от parrto

ненене дэвид блэйн, я тебя не кормлю. Но в треде уже написал, скролли вверх

я видел, но не понял. Объясни для тупого. Что за такая «суть acm»?

emulek
()
Ответ на: комментарий от parrto

Citius, Altius, Fortius!

ладно. Закончим спор, я упоролся, и уже НИЧЕГО не понимаю. Я думал, это девиз олимпиады. В контексте нашего спора, для меня загадка, что значит «Altius, Fortius», и почему ВНЕЗАПНО мне выше сказали, что «твоё „быстрее“ никому здесь не интересно».

emulek
()
Ответ на: комментарий от parrto

ответ должен быть правильным. неправильные ответы никому не нужны.

к сожалению, жизнь != олимпиада. В жизни побеждает обычно не тот, кто дальше плюнет, а тот, кому во первых повезёт, а во вторых — кто знает, когда и куда плевать. А вот доплюнет или нет — это уже третий вопрос. И обычно он значения не имеет, если первые два условия выполнены.

Если ты до сих пор не понял, то дело не в этой задаче, а в самом определении понятия «правильный ответ». А как сама задача решается — я в курсе.

emulek
()
Ответ на: комментарий от emulek

ну собственно вот до тебя и не допетривает, что никто не заморачивается в правильных формулировках, а ответ извольте дать правильным. Вот ти и проиграл по жизни. Засрал тред кучей сообщений по ПРОСТОЙ задачке. Эта задачка для 6 класса

parrto
()
Ответ на: комментарий от parrto

ну собственно вот до тебя и не допетривает, что никто не заморачивается в правильных формулировках, а ответ извольте дать правильным. Вот ти и проиграл по жизни. Засрал тред кучей сообщений по ПРОСТОЙ задачке. Эта задачка для 6 класса

мне что больше всего нравится в этом треде, так это то, что никто так до сих пор и не дал вменяемого решения ЭТОЙ задачи.

Пока победителем можно признать только код из первого поста, хотя он и с ошибкой. (: Ну и не выдаёт он решения. Только число операций(неправильно).

emulek
()
Ответ на: комментарий от emulek

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

parrto
()
Ответ на: комментарий от IvS

это поймается после вычитания (1 операция) и деления (1) операция и добавления(1 операция ) всего 3 операции , что тоже самое что добавить дважды и один раз поделить

qulinxao ★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.