Блог пользователя Fefer_Ivan

Автор Fefer_Ivan, 14 лет назад, По-русски

A. Следующий тест
Эта простая задача решается следующим образом. Заведем массив boolean used[1..3001] и заинициализируем его значениями false. Для каждого из n данных нам чисел, соответствующий элемент массива used присвоем true. Далее пройдем по массиву, начиная с 1 и найдем первое число, для которого значение used - false. Это и есть ответ.

B. Турнир
 Для решения данной задачи сначала найдем такие числа A и B, которые встретились во входных данных не n - 1, а n - 2 раз. Если переформулировать условие, то можно заметить, что отношение победившего и проигравшего транзитивно - то есть если X, выиграл Y, а Y выиграл Z, то X выиграл Z. Значит, чтобы определить кто круче - A или B, попытаемся найти такое C, у которого результат игры с A и результат игры с B различный. Если мы нашли такое С, то того игрока, который выиграл, надо вывести первым. Если такого С не существует, то любой исход матча А против B удовлетворяет условиям задачи.

C. Неотсортированная подпоследовательность
Сначала заметим, что ответ всегда либо 0, либо состоит из 3-х элементов. Однако за кубическое время искать ответ слишком долго. Вот решение за линейное время.
Будем идти по последовательности и во время каждой итерации поддерживать минимум на префиксе. Когда мы рассматриваем текущий элемент, достаточно проверить не образовавает ли этот элемент хорошую подпоследовательность с текущими максимумом и минимумом. Это не сразу очевидно, но легко доказывается. Подумайте сами над этим как домашнее задание.

D. Кольцевая 2
Рассмотрим все дороги как отрезки на числовой прямой. Дороге из города a в город b будет соответствовать отрезок [min(a, b), max(a, b)]. Для каждой пары отрезков есть 3 варианта расположения: оба конца одного отрезка внутри второго, оба конца одного отрезка вне второго и только один из концов одного внутри второго. В первых двух случаях положение дорог, соответствующих отрезкам не зависимы друг от друга. В третьем же случае дороги должны проходить по разные стороны от кольца.
Построим такой граф: вершины будут соответствовать дорогам, а ребро между вершинами i и j будет означать, что эти дороги должны лежать по разные стороны. Мы свели задачу к следующей: есть неориентированный граф. Необходимо раскрасить все его вершины в 2 цвета так, чтобы никакие 2 вершины одинакового цвета не соединялись ребром. Это делаеться при помощи, например, dfs'са. Изначально цвет каждой вершины - -1. Циклом for пойдем по вершинам. Если цикн натыкается на -1-вершину, то присваивает ей цвет 0 и запускает из неё dfs. dfs просматривает все соседи, переданной ему вершины. Если видит -1-вершину, то красит её в цвет, противоположный цвету текущей вершины и запускается из неё, иначе он сравнивает цвета текущей вершины и рассматриваемого соседа. Если они совпали, то выводим Impossible. После такого dfs'а получим ответ.

E. Число с заданным количеством делителей
Рассмотрим число, являющееся ответом и разложим его на простые множители. Получим такое произведение p1a1· p2a2· ... · pkak. Произведение по i всех ai + 1 и будет числом делителей. То есть если мы возьмем десять простых и перемножим, то уже получим число с 1024-мя делитемяли. Отсюда следует, что нам понадодиться максимум первые десять простых чисел для того, чтобы построить нужное число.
  Рассмотрим следующую динамику: d[i][j] = наименьшее число с i делителями и составленное из первых j простых чисел. Для вычисления состояния (i, j) переберем степень с которой j-е простое число войдет в ответ. Если j-е простое число входит со степенью k, то d[i][j] = d[i / (k + 1)][j - 1] * prime[j]k. По всем возможным переходам надо выбрать минимум.
Во время реализации надо быть предельно осторожным, так как все вычисления происходят на грани переполнения.

На этом все. Надеюсь, вы теперь разберетесь в задачах, дорешаете их и на следущем контесте перейдете в первый дивизион. Любые замечания и вопросы оставляйте в комментах. Если что-то не так - исправлю. С уважением, Иван.

  • Проголосовать: нравится
  • +16
  • Проголосовать: не нравится

14 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится
Спасибо за разбор!
нельзя ли узнать тест 11 на задачу С.
Очень хочется понять на чем завалилось решение.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Не знаю что за тест.

    У тебя такое же решение или другое?

    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      У меня также не прошел 11 тест. Идея решения: умножаем разность первого числа и предпоследнего на разность предпоследнего и последнего. Если она отрицательна, то подпоследовательность найдена. Наверно в 11 тесте эти числа оказались порядка 10  , -10 6   и 10 Произведение в этом случае выйдет за пределы int64.

      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Не обязательно, что первый и последний элемент участвуют в ответе.
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          имеется в виду не конечный элемент последовательности, а последний прочитанный, т.е. всю последовательность в части тестов просматривать просматривать необязательно
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Парни, объясните, что за ошибка "Ошибка представления данных на тесте 23".

Код на шарпе:

             int n = int.Parse(Console.ReadLine());

            string[] s = Console.ReadLine().Split(' ');

            int[] a = new int[3001];
            for (int i = 0; i < n; i++)
            {
                int c = int.Parse(s[i]);
                a[c] = 1;
            }

            for (int i = 1; i < 3001; i++)
            {
                if (a[i] == 0)
                {
                    Console.WriteLine(i);
                    return;
                }
            }

Выложите тест 23, если не сложно.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Ты ничего не выводишь.

    Ответ может быть равен 3001, если первые 3000 чисел использованы.

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Спасибо, Fefer. И бывает же такое...
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Good!
I just read the article, but it's in Russian, now English!!
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Thanks...
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
2^40 fits in long type in java.
BTW, To avoid overflow you can use this idea - If A*B>C then A>C/B.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    C++ has "long long int" type that can hold numbers up to 9·1018.

    It is said that answer is lower than 1018. So when prime[j]k becomes to big, I just break from the cycle. Also, because 10-th prime is only 29 me can assume, that if some var is overflowed, this var is negative. So check this also.

14 лет назад, # |
  Проголосовать: нравится +15 Проголосовать: не нравится
B имеет ещё одно простое решение: считаем количество побед и поражений каждого участника, находим тех, которые не сыграли N-1 матч. Очевидно, что из них победит тот, у кого больше побед, если побед одинаковое количество, то мы не знаем кто победит и выводим в любом порядке.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
For problem we consider that the road can be build only in clockwise direction. What about the possibility that we can build the road in anti clock wise direction ? Was it implied in the problem statement that the roads will be clockwise?
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    I meant problem D: Ring Road 2
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Sorry, for the silly question. It wouldn't matter as i just realized, since irrespective of direction they will have conflict and hence must be placed in opposite sides.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
скажите, почему вылетает ошибочный вывод на 7 тесте. программа Турнир
int main()
{
    int Nomer[2][1225], A[2], Buf[2500], chislo, test, N, i, j, k=0, m=0, q;
   
    cin>>chislo;
    N=chislo*(chislo-1)/2;
    for (i=0; i<N-1; i++)
        cin>>Nomer[0][i]>>Nomer[1][i];
    m=0;
    for (i=0; i<2; i++)
        for (j=0; j<N-1; j++)
        {
            Buf[m]=Nomer[i][j];
            m++;
        }
    for(i=0; i<m-1; i++)
        for(j=i; j<m; j++)
            if(Buf[i]>Buf[j])
            {
                test=Buf[i];
                Buf[i]=Buf[j];
                Buf[j]=test;
            }
    j=Buf[0];
    i=1;
    q=0;
    while(i<=m)
    {
        k=1;
        while((j==Buf[i])&&(i<=m))
        {
            k++;
            i++;
        }
        if (k<chislo-1)
        {
            A[q]=j;
            q++;
        }
        j=Buf[i];
        i++;
    }

    cout<<A[0]<<" "<<A[1]<<endl;
       
    system("Pause");
    return 0;
}
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Во-первых

while((j==Buf[i])&&(i<=m)) - проверки надо делать в другом порядке. Иначе выйдешь за грань массива.

Во-вторых

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

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
E: Можно искать числа вида p1a1·p2a2·...·pkak, где {ai} - неубывающая последовательность.

D: Решение существует, тогда и только тогда, когда в графе нет циклов нечетной длины (равносильно тому, что граф является двудольным). 

Проще проверить поиском в ширину, цикл присутствует, если distance[u] & 1 == distance[v] & 1.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Спс за разбор Вань)
Кстати знаю на задачу С еще круче решение: для начала если элемент равен предыдущему то мы не кладем его в вектор при считывании. Далее одинаковых подряд идущих элементов нет, значит, если какой-то элемент либо больше соседей, либо меньше их-то вывести всю тройку, иначе если такого элемента нет-это легко доказать-последовательность отсортирована.
»
3 года назад, # |
Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

For problem Div2D, could anyone explain why two color painting gives a correct answer and what the logic behind it is? Thanks.

EDIT 2: Fellow coder helped understanding the idea. SOLVED.