Python, 76 73 67 байт
f=lambda n,k=1:1-any(a**-~k*~-a**k%n for a in range(n))or-~f(n,k+1)
Попробуйте онлайн!
Еще один байт можно сохранить, вернув True вместо 1 .
Альтернативная реализация
Используя тот же подход, @feersum также предлагает следующую реализацию, которая не использует списочные выражения.
f=lambda n,k=1,a=1:a/n or(a**-~k*~-a**k%n<1)*f(n,k,a+1)or-~f(n,k+1)
Обратите внимание, что эта реализация требует времени O (n λ (n) ) . Эффективность может быть значительно улучшена при уменьшении оценки до 66 байт , но функция вернет True для входа 2 .
f=lambda n,k=1,a=1:a/n or~-a**k*a**-~k%n<1==f(n,k,a+1)or-~f(n,k+1)
Задний план
Определения и обозначения
Все используемые переменные будут обозначать целые числа; n , k и α будут обозначать натуральные числа; и р будет обозначать положительное простое число .
а | b, если b делится на a , т. е. если существует такое q , что b = qa .
a ≡ b ( mod m), если a и b имеют одинаковый вычет по модулю m , т. е. если m | а - б .
λ (n) наименьшее k такое, что a k ≡ 1 ( mod n), т. е. такое, что n | к - 1 - для всех а , которые взаимно просты с п .
f (n) наименьшее k такое, что a 2k + 1 ≡ a k + 1 ( mod n) - т.е. такое, что n | a k + 1 (a k - 1) - для всех а .
λ (n) ≤ f (n)
Fix п и пусть а взаимно простые в п .
По определению f , n | a f (n) +1 (a f (n) - 1) . Поскольку a и n не имеют общего простого множителя, также не существует a f (n) +1 и n , из чего следует, что n | a f (n) - 1 .
Поскольку λ (n) - наименьшее целое число k такое, что n | a k - 1 для всех целых чисел a , взаимно простых с n , из этого следует, что λ (n) ≤ f (n) .
λ (n) = f (n)
Поскольку мы уже установили неравенство λ (n) ≤ f (n) , достаточно проверить, что k = λ (n) удовлетворяет условию, определяющему f , т. Е. Что n | a λ (n) +1 (a λ (n) - 1) для всех a . Для этого установим, что p α | a λ (n) +1 (a λ (n) - 1) всякий раз, когда p α | N .
λ (k) | λ (n) всякий раз, когда k | n ( источник ), поэтому (a λ (k) - 1) (a λ (n) -λ (k) + a λ (n) -2λ (k) + ⋯ + a λ (k) + 1) = a λ (n) - 1 и, следовательно, a (k) - 1 | a λ (n) - 1 | a λ (n) +1 (a λ (n) - 1) .
Если a и p α взаимно просты, по определению λ и выше, p α | a λ (p α ) - 1 | a λ (n) +1 (a λ (n) - 1) следует по желанию.
Если a = 0 , то a λ (n) +1 (a λ (n) - 1) = 0 , который делится на все целые числа.
Наконец, мы должны рассмотреть случай, когда a и p α имеют общий простой множитель. Поскольку p простое, это означает, что p | а . Теорема Кармайкла устанавливает, что λ ( pα ) = (p - 1) pα - 1, если p> 2 или α <3, и что λ ( pα ) = pα - 2 в противном случае. Во всех случаях λ (p α ) ≥ p α - 2 ≥ 2 α - 2 > α - 2 .
Therefore, λ(n) + 1 ≥ λ(pα) + 1 > α - 1, so λ(n) + 1 ≥ α and pα | pλ(n)+1 | aλ(n)+1 | aλ(n)+1(aλ(n) - 1). This completes the proof.
How it works
While the definitions of f(n) and λ(n) consider all possible values of a, it is sufficient to test those that lie in [0, ..., n - 1].
When f(n, k) is called, it computes ak+1(ak - 1) % n for all values of a in that range, which is 0 if and only if n | ak+1(ak - 1).
If all computed residues are zero, k = λ(n) and any
returns False, so f(n, k) returns 1.
On the other hand, while k < λ(n), 1-any(...)
will return 0, so f is called recursively with an incremented value of k. The leading -~
increments the return value of f(n, k + 1), so we add 1 to f(n, λ(n)) = 1 once for every integer in [1, ..., λ(n) - 1]. The final result is thus λ(n).