Оценить модульные электростанции


13

Учитывая два числа n и m, оцените бесконечную башню власти:

n ^ (n + 1) ^ (n + 2) ^ (n + 3) ^ (n + 4) ^ ... mod m

Имейте в виду, что ^ является правоассоциативным. Так что 2 ^ 3 ^ 4 = 2 ^ (3 ^ 4). Теперь, как вы можете присвоить значение бесконечной последовательности правоассоциативных операторов?

Определите f (n, m, i) как энергетическую башню, содержащую первые i члены бесконечной энергетической башни. Тогда существует некоторая постоянная C такая, что для каждого i> C f (n, m, i) = f (n, m, C). Таким образом, вы можете сказать, что бесконечная энергетическая башня сходится к определенной величине. Мы заинтересованы в этой ценности.


Ваша программа должна быть способна вычислить n = 2017, m = 10 ^ 10 менее чем за 10 секунд на приемлемом современном ПК. То есть, вы должны реализовать реальный алгоритм, без грубого обращения.

Вы можете предположить, что n <2 30 и m <2 50 для числовых пределов в вашем языке программирования, но ваш алгоритм теоретически должен работать для любого размера n , m . Однако ваша программа должна быть корректной для входных данных в этих пределах размера, переполнения промежуточных значений не освобождаются, если входные данные находятся в этих пределах.

Примеры:

2, 10^15
566088170340352

4, 3^20
4

32, 524287
16

Совет (для претендентов): nи mкоторые не гарантированы совместно премьера.
Утренняя монахиня

1
10 ^ 10 (и 10 ^ 20, и, возможно, 3 ^ 20 для целых чисел со знаком) больше, чем целочисленные типы многих языков по умолчанию. Требуется ли поддерживать этот большой вход?
Дверная ручка

1
@orlp Это "да" включает 10 ^ 20? Поскольку это не вписывается в 64-битное целое число, поэтому, если вы хотите, чтобы оно требовалось, я бы предложил указать это явно, потому что в противном случае вы получите много неправильных ответов от людей, которые просто предполагают, что 64-битное целые числа будут достаточно точными.
Мартин Эндер

1
В любом случае, то , что это самый большой вход , мы должны поддерживать?
Мартин Эндер

@ Doorknob Я добавил более мягкие ограничения на вызов. Однако ваш алгоритм теоретически должен работать для любого размера m, n .
orlp

Ответы:


7

Pyth, 23 байта

M&tG.^HsgBu-G/GH{PGGhHG

Определяет функцию g, принимая m и n в этом порядке.

Попробуйте онлайн

Как это устроено

M&tG.^HsgBu-G/GH{PGGhHG
M                         def g(G, H):
 &tG                        0 if G == 1, else …
                 PG         prime factors of G
                {           deduplicate that
          u-G/GH   G        reduce that on lambda G,H:G-G/H, starting at G
                              (this gives the Euler totient φ(G))
        gB          hH      bifurcate: two-element list [that, g(that, H + 1)]
       s                    sum
    .^H               G     H^that mod G

Python 2, 109 76 байт

import sympy
def g(n,m):j=sympy.totient(m);return m-1and pow(n,j+g(n+1,j),m)

Попробуйте онлайн!

Почему это работает

Мы используем следующее обобщение теоремы Эйлера .

Лемма. п 2φ ( м )п φ ( м ) ( по модулю т ) для всех п (или нет п взаимно прост с т ).

Доказательство: Для всех простых степеней p k, делящих m ,

  • Если p делит n , то, поскольку φ ( m ) ≥ φ ( p k ) = p k - 1 ( p - 1) ≥ 2 k - 1k , имеем n 2φ ( m ) ≡ 0 ≡ n φ ( m ) (мод р к ).
  • В противном случае, поскольку φ ( p k ) делит φ ( m ), теорема Эйлера дает n 2φ ( m ) ≡ 1 ≡ n φ ( m ) (mod p k ).

Следовательно, n 2φ ( m )n φ ( m ) (mod m ).

Следствие. Если k ≥ φ ( m ), то n kn φ ( m ) + ( k mod φ ( m )) (mod m ).

Доказательство: если k ≥ 2φ ( m ), лемма дает n k = n 2φ ( m ) n k - 2φ ( m )n φ ( m ) n k - 2φ ( m ) = n k - φ ( m ) ( mod m ) и повторяем до тех пор, пока показатель степени не станет меньше 2φ ( m ).


Как это справляется со случаем, когда основание и модуль не взаимно просты? PS Симпи имеет функцию totient.
orlp

@ или я добавил доказательство. Не уверен, как я пропустил sympy.totient.
Андерс Касеорг

Я вижу сейчас. Хороший метод!
orlp

5

Haskell , 156 байт

(?)принимает два Integerс и возвращает Integer, используйте как (10^10)?2017(обратный порядок по сравнению с OP.)

1?n=0
m?n=n&m$m#2+m#2?(n+1)
1#_=1
n#p|m<-until((<2).gcd p)(`div`p)n=m#(p+1)*1`max`div(n*p-n)(p*m)
(_&_)0=1
(x&m)y|(a,b)<-divMod y 2=mod(x^b*(mod(x*x)m&m)a)m

Попробуйте онлайн! (На этот раз я проверю случаи в заголовке, поскольку они используют обозначение возведения в степень).

Любопытно, что самый медленный тестовый пример - это не тот, у которого ограничение скорости (это почти мгновенно), а 524287 ? 32тот, потому что он 524287имеет гораздо большее простое число, чем появляется в коэффициентах других тестовых случаев.

Как это устроено

  • (x&m)yэто x^y `mod` m, или сила мод, используя возведение в степень путем возведения в квадрат.
  • n#pэто функция Эйлера n, предполагая, что nне имеет меньших простых факторов, чем p.
    • mэто nсо всеми pфакторами разделены из.
    • Если есть kтакие факторы, то пациент должен сам получить соответствующий коэффициент (p-1)*p^(k-1), который рассчитывается как div(n*p-n)(p*m).
    • 1`max`...обрабатывает случай, когда nфактически не делится на p, что делает другой аргумент maxравным 0.
  • Основная функция m?nиспользует его, когда yон достаточно велик, n^y `mod` mто же самое, что n^(t+(y`mod`t)) `mod` mи когда tнаходится в m. (The t+необходим для тех главных факторов nи mимеет в общем, что все получает развернутые.)
  • Алгоритм останавливается, потому что итерированные totient функции в конечном итоге достигают 1.

1

Mathematica, 55 байт

n_~f~1=0;n_~f~m_:=PowerMod[n,(t=EulerPhi@m)+f[n+1,t],m]

Примеры:

In[1]:= n_~f~1=0;n_~f~m_:=PowerMod[n,(t=EulerPhi@m)+f[n+1,t],m]

In[2]:= f[2, 10^15]

Out[2]= 566088170340352

In[3]:= f[4, 3^20]

Out[3]= 4

In[4]:= f[32, 524287]

Out[4]= 16

In[5]:= f[2017, 10^10]

Out[5]= 7395978241

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.