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

Автор I_love_natalia, 13 лет назад, По-русски
Ответа на комментарий по задаче так и не получил, поэтому перепост.

Мне кажется, для любых a и t верно утверждение



если



Это связано с тем, что в последовательности предпериод не превосходит степени максимального простого в t, а период после разложения t = t1t2 на часть t1, взаимно простую с a и все остальное будет совпадать по длине с периодом , делителем , делителем

Прошу доказать строго или опровергнуть.

Примитивной программой проверил до t <= 100, n < t*4, работает.


Как использовать этот факт, если это верно? 

Например, расчет быстрым возведением в степень требует либо представления числа n в двоичной системе счисления, либо использования десятичного возведения в степень с плохой константой. При ограничениях a, b ≤ 106, n ≤ 1010000000 быстрое возведение в степень невозможно.

С уточнениями от freopen

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

13 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится
Можно также адаптировать алгоритм быстрого возведения в степень для десятичной системы счисления.

pow(a,b):
  res=1
  if (b>=10) res=pow(a,b/10);
  res=res*res*res*res*res*res*res*res*res*res;
  for (i=0;i<b%10;i++) res*=a
  return res
  • 13 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Это понятно. Можно и в двоичную число длиной 100к знаков за секунду-другую перевести.

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

    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      1. Как перевести 100k знаков в двоичную систему?
      2. Почему делить длинное на короткое быстрее, чем вообще решение без длинки?
      • 13 лет назад, # ^ |
        Rev. 4   Проголосовать: нравится 0 Проголосовать: не нравится

        2. Указанное быстрое возведение в степень требует 19 умножений и делений 64-битных чисел на разряд N.

        Деление длинного на короткое потребует 1 умножение и деление 32-битных чисел на разряд N. От умножения, при желании, можно избавиться.

        1. Надо проверять. Для задачи дьявольская последовательность на Тимусе я сдавал решение, которое за 0.421 секунды вычисляло значение (2/3) * (1/2)^N для N <= 100000 c точностью 30000 десятичных знаков.

        Поправка: 0.14 секунды на настоящий момент.

        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Я вообще не понимаю, зачем нужно вообще деление чего-то на что-то? Остаток же элементарно вычисляется и без этого. Просто десятичное число представляется как a0*100 + a1*101 + ... + an*10n и затем просто последовательно возводим 10 в степени 0...n и прибавляем к ответу что нужно. Код получается вроде такого:

          int ans = 0, cur = 1;
          for (int i = 0; i < n; ++i) {
            ans = (ans + cur * N[i]) % mod;
            cur *= 10;
          }
          • 13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            В указанном примере 1 деление и 2 умножения на каждый разряд N.
            • 13 лет назад, # ^ |
                Проголосовать: нравится +5 Проголосовать: не нравится
              Я не претендовал на супербыстрый код, просто сказал что деление длинного на короткое не нужно. 

              А насчет примера - на самом деле там надо еще cur = (cur * 10) % mod сделать, но от первого % можно избавиться делая всего 1 вычитание вместо этого.
              • 13 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится
                В любом случае, поделить длинное на короткое быстрее, чем делать 10-ное быстрое возведение в степень.
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Ну поправим немного. Будем работать с разрядами до 10^9 и возводить быстро. Тогда будет 30 умножений на 9 разрядов, т.е. ~3 умножения на разряд. Я точно не знаю, что быстрее, 3 умножения или одно деление.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Кстати, по пункту 1 могу пробовать вечером порезвиться и сообщить результаты.
        • 13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Первый вопрос не был предназначен выразить недоверие вашим методам перевода в двоичную систему. Он был для того, чтобы узнать методы. И они мне все еще интересны.
          • 13 лет назад, # ^ |
            Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

            Деление с кучей оптимизаций.

            Сейчас на моем компьютере на перевод 10^5 надо 829мс.

            На запуске сервера CF - 600мс.

            Фактически, перевод осуществляется в систему счисления с основанием 2^21 из системы счисления с основанием 10^3.

            • 13 лет назад, # ^ |
                Проголосовать: нравится +5 Проголосовать: не нравится
              Тогда моя идея явно проще и быстрее работает. Возможно, кому-нибудь она поможет.
              • 13 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                Это понятно.

                Вообще, дискуссия ушла в сторону. Если оригинальное утверждение верно, то решение будет еще проще и намного быстрее работать.

                • 13 лет назад, # ^ |
                    Проголосовать: нравится +10 Проголосовать: не нравится
                  Ну воот. А я уж подумал, что уходящие в сторону дискуссии - основная фишка CF.
                • 13 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится
                  Чего оно будет намного быстрее работать? Я сомневаюсь что будет быстрее более чем в 2 раза, и то не уверен. Надо написать и сравнить :)

                  На кодфорсес, когда-то была именно такая задача. Я тогда кодил решение с функцией Эйлера, правда предпериод руками считал, а многие сдавали так как сказал freopenПроходили оба решения. Правда я не помню номера контеста, поищу как приду домой.
                • 13 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится
                  Ого, уточнения появились. А научите считывать быстрее чем делать 3-6 умножений на разряд?
                  • 13 лет назад, # ^ |
                      Проголосовать: нравится 0 Проголосовать: не нравится
                    10 мегабайт можно считать за 0.1 секунды через fread с каким-то размером блока. А там 19 делений на разряд.
13 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится
Что именно надо строго доказать? Что предпериод не превосходит логарифма и период является делителем фи? Если это, то элементарно же доказывается.
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Ага. Вот я и хочу это "элементарно" менее на пальцах, чем я указал.
    • 13 лет назад, # ^ |
        Проголосовать: нравится +5 Проголосовать: не нравится
      для доказательства надо разложить t на множители и заметить, что если p^k | n, то \phi(p^k) | \phi(n)
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      an ≡ an - c (mod t)

      an - an - c ≡ 0 (mod t)

      an - c(ac - 1) ≡ 0 (mod t)

      То есть произведение в левой части сравнения делится на t. Сами множители этого произведения взаимно простые (думаю, понятно почему). То есть, если в факторизации t есть какие-то простые, которые присутствуют в факторизации a, то единственный способ «покрыть» эти простые — набрать достаточно большую степень an - c. Понятно, что если показатель этой степени превосходит логарифм t по основанию 2 (наименьшее простое число), то этот множитель обязательно будет делиться на t2 (в вашей нотации).

      С простыми в t2 мы уже «справились», и нам известно, что второй множитель в левой части сравнения не имеет простых делителей, общих с t2. Тогда нам осталось найти c:

      ac - 1 ≡ 0 (mod t1)

      a и t1 взаимно просты, а значит выполняется условие теоремы Эйлера.

      Сойдет?

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

Утверждение не несет какого-либо математического содержания.
Проверьте отдельно для примарных сомножителей в разложении t (либо взаимно простых с a, либо нет).
P. S. Первая правка радует.
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Утверждение из поста равносильно тому, что начиная с некоторого аргумента n теорема Эйлера начинает выполняться для любых a и t (а не только взаимно простых), причём этот аргумент сам никак не входит в модулярное уравнение в теореме Эйлера. Я прав? Если не прав, прошу поправить (вполне предполагаю такое) и объяснить, почему нет.
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
формулы не видны. не могли бы вы написать их в альтернативном виде, пожалуйста?
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Достаточно старая тема, лень, честно.
    Кажется, при обновлении сервера что-то с tex-ом приключилось.
    Идея в том, что a^b == a^{b - \phi (n)} (mod n) при b >= 2 \phi (n)