26

(32 ответов, оставленных в Problems)

Я хеширую по модулю 1027. Чтобы очистить хешсет посто заполняю массив last минус единицами (см. код добавления на предыдущей странице).

27

(5 ответов, оставленных в Problems)

Да, точно, тогда как раз выходит квадрат.

28

(8 ответов, оставленных в Algo)

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

Структура простая: Join(1,2), Join(1,3), Join(1,4), ..., Join(1,N). Предполагается, что Join выглядит следующим образом:

Join(a,b) {
 A = root(a);
 B = root(b);
 if (rand() & 1) p[A] = B; else
 p[b] = A;
}

При такой реализации с вероятностью 1/2 при каждом Join'е у дерева, содержащего вершину 1, высота будет увеличиваться на 1. Ожидаемая высота через N операций будет N/2.

29

(8 ответов, оставленных в Algo)

Да нет, с рангами там как раз все нормально. Оценивать можно и высоты.

30

(8 ответов, оставленных в Algo)

Интересно. А этот тест дает логарифм для произвольного рандсида?

31

(5 ответов, оставленных в Problems)

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

32

(5 ответов, оставленных в Problems)

Да ее вроде и за O(NlogN) решить можно, хотя тут и квадрата достаточно.

Сделаем бинпоиск по длине ответа. Теперь при фиксированной длине 2Х найдем все позиции начал К-четных строк такой длины. Понятно, что от цикличности можно избавиться просто записав исходную строку S как S+S. Рассмотрим подстроку из первых Х позиций. Найдем кол-во символов из первой половины, которые отличаются от второй половины. Теперь сдвинем эту строку на 1 вправо. Что мы получим?

Пусть были символы: 1234 5678, после сдвига станет 2345 6789. Как видно, символы 234 и 678 соответствуют друг другу как в изначальной строке, так и в сдвиге, значит нам нужно только удалить пару 1-5 и добавить 5-9, что делается за О(1). Таким образом, можно пройти по всей строке и за O(N) найти все позиции начал К-четных строк.

Теперь, когда мы знаем длину ответа, просто пройдем по всем позициям начала и выберем мин. лексикографическую строку за квадрат. Если сильно хочется O(NlogN), можно это суфф. массивом сделать.

33

(5 ответов, оставленных в Problems)

Ну вот как раз повод почитать о нем.

34

(5 ответов, оставленных в Problems)

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

35

(5 ответов, оставленных в Problems)

Все каменные дороги образуют дерево. От нас требуется изменить цены дорог таким образом, чтобы дерево из каменных дорог было минимальным остовным деревом. Эта задача решена тут.

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

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

Не знаю, что там не изменилось, но я взял ваш код, добавил в него проверку и оно получило Accepted.

for i:=1 to m do begin
   read(f,u,v,s);
   if (a[u][v]=-1) or (a[u][v]>s) then begin
   a[u,v]:=s;
   a[v,u]:=s;
   end;
 end;{считана матрица}

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

Судя по всему, вас это не очень волнует, раз за 3 дня баг не был найден. Все-таки условие нужно читать внимательно и не делать никаких предположений о том, чего в условии нет. Если в условии не сказано что в графе нет мультиребер, значит они там могут быть.

Хм... Да, действительно. Не зря я пишу только алгоритм Крускала smile

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

41

(2 ответов, оставленных в Algo)

Ответом будет длина выпуклой оболочки плюс 2*pi*r. Можете попробовать поискать что-то вроде "выпуклая оболочка окружностей одинакового радиуса". Лучше на английском искать.

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

43

(9 ответов, оставленных в Algo)

Ну, если тайм лимит не сильно маленький, то вроде бы можно так. Добавим ребро из t в t и теперь будем искать количество путей длины ровно k.

Пусть f(i,mask) это количество простых путей из s в i, в которых мы посетили только вершины из mask. Посчитаем эту динамику для всех путей длины k/2. Состояний должно быть не сильно много.

Посчитаем еще одну динамику g(i,mask) - количество простых путей из i в t, в которых мы посетили только вершины из mask. Опять же, посчитаем ее для путей длины k-k/2.

Теперь переберем центральную вершину v в пути длины k и нам надо для всех пар (mask1,mask2), которые имеют общий элемент только v посчитать сумму произведений f(v,mask1)*g(v,mask2). Для этого переберем v и mask1 и найдем сумму всех g(v,mask2), которые нам подходят.

Можно по включению-исключению: возьмем сумму всех g(v,mask2), отнимем сумму таких, которые имеют 1 общий элемент с mask1 (кроме v), затем прибавим те, которые имеют 2 и т.д. Для этого, разумеется, надо в начале сделать предподсчет по g(v,mask2).

44

(9 ответов, оставленных в Algo)

Fdg пишет:

Как найти количество путей в ориентированном графе (к-во вершин <=50) от s до t длины не более k<=10?

Динамикой по вершине и длине пути. Пусть f(i,j) - количество путей из вершины s в вершину i длины j. Тогда f(i,j)=сумма f(w,j-1) по всем w из которых есть ребро в i.

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

46

(4 ответов, оставленных в Problems)

Из простых соображений следует что количество счастливых билетов длины 2N с суммой цифр 2S равно квадрату количества чисел длины N с суммой S. Это позволяет свести исходную задачу к такой: есть N и S, нужно найти количество чисел из N цифр с суммой цифр S. Такая задача решается динамическим программированием. Кстати, формула правильная.

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

48

(4 ответов, оставленных в Problems)

Если сумма нечетна, ответ 0. Иначе считаем количество чисел с N цифрами с суммой S/2 и возводим в квадрат.

49

(1 ответов, оставленных в Problems)

Ну если ограничений на числа нет, то можно вообще просто. Изначально в каждую вершину поставим единицу. Пронумеруем все ребра. Теперь если вершины A и B соединены ребром с номером K, то умножим числа в обеих вершинах на K-е простое число. Очевидно, что если вершины не соединены ребром, то НОД их чисел равен 1.

50

(7 ответов, оставленных в Problems)

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