Задать вопрос
  • Можете помочь применить lower_bound и upper_bound в С++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    В данной задаче можно пользоваться встроенными функциями.

    надо ускорить программу с помощью lower_bound и upper_bound,


    Ну вот посмотрите на эти самые lower_bound и upper_bound в документации. Они как раз находят первое и за-последним включение заданного числа, если оно в упорядоченном массиве встречается. Если числа там нет, то они оба будут указывать на первое большее заданного число.

    Функции возвращают итераторы. Чтобы преобразовать их в индексы, можно воспользоваться std::distance, чтобы узнать расстояние до начала массива. Там по ссылкам выше прямо примеры есть, которые все это делают.
    Ответ написан
  • Как реализовать функцию копирования бит со смещениями в src и/или dst и не кратным 8 количестве бит?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Самое эффективное - использовать какой-нибудь SSE (гуглите shift bits sse. Лучше всего, мне кажется, подойдет _mm_slli_epi64). Но там очень много кода и случаев будет. Придется отдельно разбирать случаи сдвига влево и вправо, отдельно вычленять биты, которые SSE операция при сдвиге бы потеряла и записывать куда надо.

    Следующий по эффективности вариант - это читать в int64_t, и там сдвигать биты. Придется сначала из переменной доставать старшые/младшие 1-7 бит и писать их отдельно, потом сдвигать биты и записывать куда надо. Используйте memcopy для чтения/записи 64-ех бит. Еще можно ускорить, если отдельно обработать первые несколько байт до 64-битного выравнивания, и потом придется еще обрабоать отдельно лишние 0-7 байтов в конце, если их количество не делится на 8.
    Ответ написан
  • Как зашифровать алгоритм внутри программы?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Никак.

    Вы можете только усложнить реверс инжениринг. Самый эффективный способ, если не очень важна производительность, то можно реализовать собственную виртуальную машину с кучей похожих, но немного разных инструкций, и реализовывать алгоритм на ней. Надо еще впихнуть в алгоритм всяких неважных действий, типа тут прибавить 5 к числу, оно потом в алгоритме умножается на 2, потом вычесть 8 и 2. Можно написать транслятор с простого скриптового языка на ЭТО, иначе вы и сами запутаетесь.

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

    Тут та же проблема, с которой копирасты пытаются бороться: алгоритм - это информация. И если он, таки, исполняется на компьютере пользователя вы никак не можете ему запретить его смотреть, копировать или модифицировать.

    Единственный достаточно надежный способ - это выполнять алгоритм на сервере и выдавать клиенту лишь его результат. Но это совсем не то, что вы имеете ввиду.
    Ответ написан
    6 комментариев
  • Как это быстро сделать?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Перебирайте буквы от младших к старшим: a,k, d,b,z, e...

    Проверяйте правильность суммы поциферно справа на-лево как можно раньше.

    Т.е. после перебора a уже можно проверить, что (a+a+a) % 10 = a. Потом, после k надо проверить (ka+ka+ka)%100 = ka, после dbz можно проверить третью цифру.

    Можно немного соптимизировтаь, есл ине считать (ка+ка+ка)%100, а помнить, какой там перенос из младшей цифры и проверять уже только (k+k+k+carry1)%10 = k, carry2 = (k+k+k+carry1)/10; Потом проверить, что (d+b+p + carry2)%10 = z и т.д.

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

    Следующее улучшение - не перебирать буквы s, z, e и r, а сразу считать, какими они должны быть, чтобы сумма сходилась. С s и z все тривиально, а для e и r надо чуть-чуть математики.

    Это надо аккуратно выписать уравнения вида (e+a+e+carry2)%10=a.

    Тут надо применить свойства модуля: 2e %10=-carry2 % 10, Тут для e есть 2 решения, если carry2 четно: (10-carry2)/2, (20-carry2) / 2

    Но это улучшение не сильно ускорит.
    Ответ написан
  • Что значит эта ошибка?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Судя по всему, когда вы проект создавали, вы его не сделали консольным. Пересоздайте проект (кода у вас немного, его можно скопировать). Внимательно выбирайте new console application.
    Ответ написан
    4 комментария
  • Как решить задачу по C++ на алгоритмы?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Видимо, надо вывести все пары n и k, таких что k^2+n^2=n!/(k!(n-k)!), a <= k <= n <= b.
    Ответ написан
    Комментировать
  • Как решить проблему с открытием текстового файла в C?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Код выглядит правильно. Смотрите в свойствах проекта, какая директория является текщей для программы. Может быть это не папка с проектом, а папка, где лежит собранный экзешник. Попробуйте запихать файл туда.

    Попрбуйте файл засунуть в корень диска и ввести абсолютный путь до него.
    Ответ написан
    Комментировать
  • Какой алгоритм используется при возможности 2 неудачных попыток?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Предполагаю, что это известная задача, где надо минимизировать количество бросков в хужшем сулчае. Задача решается динамическим программированием.

    Пусть C(n,k) - сколько надо в худшем случае бросков, если мы знаем, что предмет разбивается при бросании с 1..n и можно сделать k неудачных бросков.

    С(n,k) = min_i=1..n-1 ( max(C(i,k-1), C(n-i, k)) )) + 1


    База - C(1, k) = 0; C(n, 1) = n-1.
    Ответ написан
    2 комментария
  • В чём ошибка кода?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    if (!((ceil(y)) % 2 && ...

    Поставьте скобки вокруг ... % 2

    Приоритет операций такой, что сначала вычислится 2 && ... и потом вы на этот bool попытаетесь поделить с остатком.

    И вообще, ваш код невозможно читать. Слишком много скобок. Во-первых, введите 4 переменные и посчитайте в них floor/ceil от x/y. Удалите очевидно лишние скобки.

    Потом вместо !(a%2) лучше писать (a % 2 == 0), а то с вашим количеством скобок вообще непонятно, к чему ! относится.
    Ответ написан
    5 комментариев
  • Как найти принадлежность точки к закрашенной области на плоскости?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Отдельно проверьте, что точка в первой четверти.

    Далее, фигура повторяется блоками 2x2, т.е. вам не важны сами координаты, а только их положение в блоке.

    Для высчитывания координаты в блоке можно или вычитать 2, пока координата больше 2, или вычесть из x (floor(x) - floor(x)%2). floor(x) даст целые числа. Потом надо это число сделать четным, возможно вычесть 1. floor(x)%2 - как раз и даст нам, что надо вычесть.

    А дальше - набор if-ов. вам надо лишь описать, что точка принадлежит одной из двух четвретринок круга в левом нижнем углу.
    Ответ написан
    Комментировать
  • Как найти принадлежность точки к такому графику?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Разбейте область на простые фигуры (квадраты, окружности, полуплоскости) и опишите логически. Вроде точка в области, если она в фигуре А, но не фигуре Б; или в фигурах В и Г, или в фигурах Д и Е.

    Далее перевести это в код - это один if с кучей условий объедененных логическими или (||) или логическими И (&&).
    Ответ написан
    Комментировать
  • Ошибка сегментирования (стек памяти сброшен на диск) c++. Как исправить?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ваша программа бесконечно уходит в рекурсию, у нее кончаетсся память и она падает. func(1, v) в цикле при i=0 вызовет func(1,v1), которая опять же вызовет func(1,v1), которая опять же... И так пока программе не поплохеет.
    Ответ написан
    Комментировать
  • Как решить эту задачу на C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Немного порешав разные суммы руками можно понять, что тут работает жадное решение - можно брать самую большую купюру, помещающуюся в оставшуюся сумму.

    Это также можно доказать. Брать более одной 100 нет смысла, их можно было бы заменть на 200. Также более двух 200 брать смысла нет - три можно разменять на 500+100, что меньше купюр. Аналогично для всех оставшихся купюр.

    Ну вот вам осталось для каждой купюры проверить, что оставшаяся сумма не меньше купюры, потом выдать сколько влезает купюр и заменить сумму на остаток от деления.
    Ответ написан
    2 комментария
  • Как разбить числа по группам так, чтобы в группах находились близкие по значению числа?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Надо ввести какую-то метрику - какая-то числовая оценка, которая говорила бы вам, почему [[1,2],[3,4],[5,6]] лучше чем [[1,2,3,4],[5],[6]]. Например, можно взять максимальную разность двух чисел в любой группе. Или сумму квадратов расстояний от всех чисел до среднего в их группе. Или минимальное расстояние между числами в разных группах (это надо максимизировать).

    Потом можно применять какой-то из известных методов кластеризации, в зависимости от выбранной метрики. В случае одного измерения, как у вас (просто числа) можно еще применить и динамическое программирование. Этот метод работает для практически любой вменяемой метрики. Считайте функцию F(n,k) - лучшая возможная метрика если первые n чисел разбить на k групп. Для пересчета надо перебрать, сколько чисел идет в последнюю группу (i), и пересчитать метрику на основе F(n-i, k-1). из всех вариантов выбрать лучший.
    Ответ написан
    Комментировать
  • Что есть максимальная сумма делителей?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Кстати, можно подсчитать эту самую сумму для всех чисел от 1 до n за линейную сложность.

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

    Далее, используя эти данные, можно подсчитать сумму всех простых делителей используя формулу S=(p1^(k1+1)-1)/(1-p1)*...*(pm^(km+1)-1)/(1-pm) (тут p1^k1...pm^km - разложение числа на простые множители).

    Надо считать эту сумму делителей от меньших чисел к большим (обозначим ее S(n)). Тогда S(n) = S(n/p^k)*(p^k*p-1)/(p-1).

    Но это так, для любопытных. Я думаю в вашей задаче достаточно для кадого числа проверять все делители до корня (а оставшиеся делители получаются как n/i, если i - делитель до корня). Надо только аккуратно разобрать случай, когда i = sqrt(n) - тогда второй делитель не надо рассматривать, ибо это вторая копия того же самого.
    Ответ написан
    3 комментария
  • Какой алгоритм вычисления кратности чисел более эффективен?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Судя по названию функции (sum) вам надо найти сумму чисел. Это делается в одно действие без циклов вообще.

    Если бы были нужны только числа делящееся на 3, то их сумма - f(n, 3)=3*floor(n/3)(floor(n/3)+1)/2. Эта формула получается вынесением 3 за скобки в сумме и дальше применением формулы армфметической прогрессии.

    Чтобы взять сумму делящихся на 3 или 5 надо взять сумму делящихся на 3, прибавить сумму делящихся на 5 и вычесть сумму делящихся на 15. Потому что делящиеся на 15 были подсчитанны 2 раза в первых слагаемых. Т.е. ответ - f(n,3)+f(n,5)-f(n,15)
    Ответ написан
    Комментировать
  • Влезет ли параллелепипед в четверть цилиндра?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Раз коробка должна стоять одной гранью на полу, то можно перебрать, какая же из них на полу, проверить что прямоугольник помещается в сектор круга и третье измерение коробки не превосходит высоты цилиндра.

    Как проверить прямоугольник на впихивание в сектор? Если коробка помещается, ее можно в секторе вертеть и двигать, пока она не будет касаться границы сектора тремя вершинами. Получаются случаи: угол коробки совспадает с уголом сектора (диагональ прямоугольника <= радиуса), одна точка на прямой стороне сектора и две на круглой, 2 угла на двух прямых сторонах и одна на круглой.

    Два последних случая надо порисовать, ввести какие-то переменные (например во втором случае можно ввести x и y - длины отрезков от угла сектора до углов прямоугольника) решить систему квадратных уравнений (длины сторон заданны, третья точка лежит на окружности) и проверить, что четвертая, свободная точка лежит внутри.

    Что бы не плодить еще и случаи с порядком вершин советую перебрать 3! перестановок всех длин параллелипипида. Третья всегда будет высотой, дву другие в заданном порядке задают расположение точек. Например в первом случае первая длина - будет шириной прямоугольника, а вторая - высотой. В случае касания двумя точками двух прямых сторон, первая длина - будет стороной отсекающей угол, и т.д.

    Вот так перебрав все случаи различных расположений коробки надо проверить, что хотя бы один из них помещается в ваш цилиндр.
    Ответ написан
  • Алгоритм перевода RGB-компонент в длину волны?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Тут не тег "физика" нужен, а "биология". С точки зрения физики - эта задача не имеет смысла, ну не соответствует набор интенсивности трех длин - длине какого-то другого цвета.

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

    Еще надо помнить про специфику работы мониторов - эти самые числа в RGB задают квадратные корни интенсивности свечения разных пикселей.

    Еще, возможно будет легче сначала преобразовать RGB в какой-нибудь YUV или HSL.
    Ответ написан
    1 комментарий
  • Нужно ли знать +- ассемблер, чтобы изучать C?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Всем программистам стоит пройти хотя бы ознакомительный курс ассемблера. Особенно тем, кто пишет на отсносительно близких к железу языках, вроде Си.

    Это здорово вправляет мозги. Появляется понимание, а как вообще компьютер работает. Это не необходимое знание, конечно, но лишним оно не будет точно.
    Ответ написан
    Комментировать
  • Как отправить файл на почту?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    желательно используя средства только голого c++, без библиотек?


    Если вы в линуксе, то введите в терминале "man sendmail". Разберитесь с командой и вызывайте ее из C++ программы через system.

    Иначе - разбирайтесь с сокетами, протокалами SMTP, TCP. Простенький клиент строчек на 3000 сможете написать через пару месяцев, наверное. Ну, или, все-таки, пересмотрите ваши условия и используйте библиотеки или более удобный для этого язык. Так в питоне это делается буквально в 2 строчки.
    Ответ написан
    Комментировать