В случае, когда n намного длиннее 2 ^ p, вы можете избежать некоторой боли в квадратичном времени, выполнив что-то вроде этого:
def mod1(n,p):
while n.bit_length() > 3*p:
k = n.bit_length() // p
k1 = k>>1
k1p = k1*p
M = (1<<k1p)-1
n = (n & M) + (n >> k1p)
Mp = (1<<p)-1
while n.bit_length() > p:
n = (n&Mp) + (n>>p)
if n==Mp: return 0
return n
[отредактировано, потому что я испортил форматирование раньше; спасибо Бенджамину за указание на это. Мораль: не копируйте и не вставляйте из неактивного окна в SO. Извините!]
(Примечание: критерий уменьшения длины n вдвое, а не снятия p, и точный выбор k1 оба немного ошибочны, но это не имеет значения, поэтому я не стал их исправлять.)
Если я беру p = 12345 и n = 9 ** 200000 (да, я знаю, что p тогда не простое число, но здесь это не имеет значения), то это примерно в 13 раз быстрее.
К сожалению, это не поможет вам , потому что в тесте L-L n никогда не больше, чем примерно (2 ^ p) ^ 2. К сожалению.