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

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

Сегодня у меня попалась комната, ну очень хорошая для взломов. Листаю я коды (Задача А div. 2), и тут натыкаюсь на явно квадратичное решение, а ограничения на длину строк 10^5.

Пишу тест:

aaaaaa...aaa(10^5)

bbbbbb...bbb(10^5)

Отправляю просто скопировав из файла, который вывел мне мой тестген. Выходит ошибка, что невозможно обработать тест. Потом пробую отослать сам файл(txt) с тестом. Ошибка та же.

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

Думаю, ну ладно. Пишу генератор:

for (int i = 0; i < (int)1e5; i++)

cout << 'a';

cout << endl;

for (int i = 0; i < (int)1e5; i++)

cout << 'b';

cout << endl;

Отправляю, выходит ошибка "**Неизвестный вердикт:GENERATOR_CRASHED**", оказывается, генератор работает долго.

Не печалюсь, исправляю все на printf, ошибка та же.

Попробовала putchar, все равно ТЛ.

Думаю, запишу ка я все в строку, а потом выведу ее. Получаю ошибку памяти (ML).

В итоге, получилось завалить решение, когда я создавала строку длиной не 10^5, а только 30000.

Убила очень много времени, чтобы подогнать, чтобы не было ML и TL.

Как вообще поступать в таких ситуациях? А если бы решение было не совсем квадратичное, и на 30 000 заходило бы(со скрипом), а на 100 000 уже нет?

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

»
13 лет назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится
#include <iostream>

using namespace std;

int main() {
  for (int i = 0; i < 100000; ++i) {
    cout << 'a';
  }
  cout << endl;
  for (int i = 0; i < 100000; ++i) {
    cout << 'b';
  }
  cout << endl;
  return 0;
}

Вот этот код в запуске работает 30 мс.

Как вариант, можно засунуть всё в char[], создать строку от этого массива и вывести её.

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    Вы попробуйте лучше все выводить у себя на компьютере. В консоль. Там оно действительно работает долго. Со строками работало быстро, но ВНЕЗАПНО получало ML. Могу предоставить все скриншоты.

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится

      Да, как ни странно, вывод в консоль 10^5 символов будет долгим) Вообще, и 10^6 обычно без проблем запросто генератором выводится.

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

        Каким генератором?

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

          Тем, что приведен в тексте блога, или в комментарии выше. P.S. я имею ввиду, на сервере

    • »
      »
      »
      13 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

      Проверил, локально все символы выводятся в пределах 20 мс.

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

    Если честно, меня очень удивляет, как оно тут за 30 мс работает...

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

    может на сервере он работает так быстро, потому что выводит первые 255 символов, и дальше перестает выводить

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

      Да да да.

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

      Это не так на сервере решение запускается полностью просто выводится префикс вывода.

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

Эту ошибку получает код выше.

А эту — со строками.

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

    Блин, ну в 10-то секунд он должен был уложиться. Проблема в чём-то другом.

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

      Со строками, у меня есть еще одна посылка, на 50 000, и она тоже ловит ML. Почему???

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

        Может какие-то лишние параметры генератора?

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

          нет. Там генератор у меня считывал длину n, и до n выводил строки "aaaa" и "bbbb". В скриншотах я вводила как раз 100000.

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

            Скорее всего в этом и проблема, выложи считывание.

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

              Печально, что исходники нельзя глянуть. Сейчас восстановлю весь код. вот он

              вот такой вот был код. Точь-в-точь.

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

                Параметры генератора передаются в argv, а не считываются через cin)) Прога просто либо не считывала, и в n шлак был, либо ждала ввода, как я понимаю.

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

                  что?

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

                  Стоп, а когда я вводила также n = 30000, все зашло.

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

                  int main(int argc, char *argv[]), а потом atoi(argv[0]), или atoi(argv[1]) если еще имя приложения передается

              • »
                »
                »
                »
                »
                »
                »
                »
                13 лет назад, # ^ |
                Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

                Что? Генератору-то на вход ничего не даётся, и

                cin >> n;
                

                будет ждать вечно.

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

                  =================================================== А зачем ему параметры тогда вообще? Как надо было писать?

                  p.s. почему-то исчезла возможность смотреть свои взломы, или я просто уже ничего не вижу.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                  Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

                  ========================================================== Странно как-то. Я вроде также делала, для n = 30000, и все зашло. О_О

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

                  Можно в argv что-нибудь разное передавать, не меняя код генератора.

              • »
                »
                »
                »
                »
                »
                »
                »
                12 лет назад, # ^ |
                  Проголосовать: нравится +8 Проголосовать: не нравится

                Ну и... Почему нельзя было задать n константой?..

      • »
        »
        »
        »
        13 лет назад, # ^ |
        Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

        Потому что при каждом «str += 'a';» создаётся новый объект с буфером, размер которого равен размеру строки. Так что общий расход памяти будет превосходить 2 * sizeof(char) * (1 + ... + 50000).

        Upd: неправда, см. комментарии ниже.

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится +4 Проголосовать: не нравится

          Казалось бы, при += как раз происходит перевыделение, а не создание нового — примерно как с vector<>::push_back.

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

            Ок, насчёт operator+= — спорно (надо смотреть реализацию STL), но operator+ точно должен выделять новый буфер.

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

              Он новый выделит, старый-то он освободит.

              • »
                »
                »
                »
                »
                »
                »
                »
                13 лет назад, # ^ |
                Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

                Угу, и 100к выделений памяти небесплатны.

                Почему ML — хрен его знает.

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

            Проверил, += действительно не пересоздаёт постоянно буфер.

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

          Так, а как поступать в итоге?

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится +1 Проголосовать: не нравится

            Никак. Это правильно, лишняя память будет при str=str+a, и то, не очень много. Может файл не тот отправляешь?

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

              Нет =) Это исключено =) Я очень много раз отсылала, и проверяла много раз, что отсылаю то, что нужно =) Взломала я этого человека с 9 раза )

»
13 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Взламывал спокойно генераторами вида

print 'a'*10**5

print 'b'*10**5

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

»
13 лет назад, # |
Rev. 2   Проголосовать: нравится -8 Проголосовать: не нравится

Какой-то генератор к предыдущему соревнованию:

#include <cstdio>

int main()
{
  #ifdef LocalHost
    freopen("text.in", "r", stdin);
    freopen("text.out", "w", stdout);
  #endif
  puts("100000");
  for (int i = 0; i < 100000; i++)
    printf("%d%c", i + 1, " \n"[i == 99999]);
  return 0;
}

Возможно, меня спасает ifdef... Без него не пробовал.

»
12 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

Оффтоп, но меня по поводу взломов интересовало две вещи:

1) Можно ли юзать обфускаторы кода? :) Тогда смотрящий точно не поймет, в чем слабость алгоритма. Особенно применяется к антихеш-тестам для конкретного основания хеша и способа хеширования, которые в тестировании встретятся наврядли. 2) Скопировать чужой код, я так понял, из окошка взлома нельзя (чтобы проверить какой-то тест на правильность). А зачем это сделано? Сам не встречал, но неужели нет какого-нибудь OCR для этого, напечатанный код то с картинки распознать, или вообще как-то напрямую? Задача интересная )

Если минусуете, то популярно объясните, почему.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +2 Проголосовать: не нравится
    1. На Topcoder в явном виде запрещено. Тут, видимо, нет, но Вам же хуже: не узнаете о неверности решения во время контеста — точно потеряете баллы.

    2. Нет, нельзя. Сделано, например, чтобы нельзя было застрессить решение со своим "правильным" и вбить тест. OCR, конечно, бывают (например, которые распознают фото документов), но я не видел, чтобы кто-то с этим заморачивался.

    • »
      »
      »
      12 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
      1. Я как раз отметил не "неверные" решения, а "почти всегда работающие" :) Например хеши со специфичным основанием, которые не взламываются итоговыми тестами, или какие-то костыли, с которыми, например, макстест проходит по времени, а немножко (но правильно) измененный — нет. Так что от взлома такого решения автор именно потеряет.

      2. Да, именно для этой цели и имеется в виду. А ведь если заморочиться и автоматизировать процесс, профит будет серьезный, нет?

      (мне просто любопытно)

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

      Про OCR здесь выглядит абсолютной халявой, т.к. убиваем цвет + считаем корреляцию должно давать 0% ошибок.

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

        Вот-вот, распознать идеальную картинку задача вообще простая и даже не творческая ) Поэтому и думается, что кто-то, да заморочился.

  • »
    »
    12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    1) Допустим, что в решении участника есть ошибка. Рассмотрим две стратегии: а) решение обфусцировано, его никто не взломает; б) решение не обфусцировано, тогда кто-то его взломает.

    В случае а) имеем: решение не взломано и падает на системном тестировании. Участник: +0 очков, потенциальный взломщик: +0 очков.

    В случае б): решение взломано, с немалой вероятностью участник находит ошибку и перепосылает правильное решение. Участник: +300—… очков, взломщик: +100 очков.

    Ну и какая стратегия лучше для участника?

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

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

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится

      Обфускации бывают разные. Я например на CF разок получил -50 за попытку челленджа по обфусцированному решению — сначала было написано правильное решение, потом return, потом неправильное ровно на страницу просмотрщика. С такой стратегией взломщик (прокрутивший решение до конца и увидивший баг) получает -50, а участнику-обфускатору от такого никаких убытков.

      И да, что-то я в правилах не нахожу ничего про запрет OCR/перехват текста программы до рендеринга флешом.

»
12 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

В Codeforces Round 155 (Div. 2) я пытался взломать решение, где был выделен массив на 3000, хотя в худшем случае может использоваться 3*10^5. Написал генератор на паскале:

var i :longint;
Begin
  writeln('100000');
  write('1');
  for i:=2 to 100000 do write(' ',1);
  writeln;
end.

Получил ошибку (некорректный тест) FAIL Unexpected character #13, but ' ' expected (stdin). Может кто-нибудь знает, в чем дело?

  • »
    »
    12 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится -11 Проголосовать: не нравится

    Найден перенос строки. Ожидался пробел

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится

    Там надо было 2*n чисел во второй строке выводить

»
12 лет назад, # |
Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

код 13 — переход на новую строку, значит последний writeln не нужен.

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

спасибо, понял ошибку, жалко, что 100 баллов потерял(