малая теорема подход Ферма является математически осмысленная один, и только mulitplying снова и снова 7 mod 10^6 - простейший код, но есть другой подход, который вы могли бы принять, что является вычислительно эффективным (но требует более сложного кода). Во-первых, обратите внимание, что при умножении на 7 цифра последней зависит только от цифры последней цифры (т. Е. Мы делаем все mod 10).Умножим раз на 7, чтобы получить
7 (4)9 (6)3 (2)1 (0)7 ...
Хорошо, отлично, так что если мы хотим 3, мы начинаем в 7^3 и идти каждый 7^4 оттуда. Теперь заметим, что при умножении на 7^4 последние две цифры зависят только от двух последних цифр 7^4 и двух последних цифр предыдущего ответа. 7^4 - 2401. Таким образом, последние цифры всегда будут одинаковыми при увеличении на 7^4.
Как насчет последних трех? Ну, 7^3 = 343 и 7^4 заканчивается 401, поэтому мода 1000 мы получаем
343 543 743 943 143 343
Мы получили наши первые три цифры в колонке # 2 (543), и мы видим, что последовательность повторяется 5 раз, поэтому мы должны подняться оттуда на 7:20.
Мы можем повторять этот трюк снова и снова: найдите, как часто повторяется следующий блок цифр, найдите нужную подпоследовательность внутри этого блока, а затем умножьте не на 7, а на 7^n.
То, что мы действительно делаем, это найти (мультипликативное) кольцо над меткой m'th, а затем умножить размеры всех колец вместе, чтобы получить промежуток между последовательными степенями, которые имеют одинаковые N цифр, если мы последуем Этот метод. Вот некоторые Scala код (2.8.0 Beta1), что делает именно это:
def powRing(bigmod: BigInt, checkmod: BigInt, mul: BigInt) = {
val powers = Stream.iterate(1:BigInt)(i => (i*mul)%bigmod)
powers.take(2+powers.tail.indexWhere(_ % checkmod == 1)).toList
}
def ringSeq(digits: Int, mod: BigInt, mul: BigInt): List[(BigInt,List[BigInt])] = {
if (digits<=1) List((10:BigInt , powRing(mod,10,mul)))
else {
val prevSeq = ringSeq(digits-1, mod, mul)
val prevRing = prevSeq.head
val nextRing = powRing(mod,prevRing._1*10,prevRing._2.last)
(prevRing._1*10 , nextRing) :: prevSeq
}
}
def interval(digits: Int, mul: Int) = {
val ring = ringSeq(digits, List.fill(digits)(10:BigInt).reduceLeft(_*_), mul)
(1L /: ring)((p,r) => p * (r._2.length-1))
}
Таким образом, если мы нашли один случай цифр, которые мы хотим, мы можем теперь найти их все, находя размер соответствующего кольца. В нашем случае, с 6 цифр (то есть по модулю 10^6) и основания 7, мы находим размер повтора:
scala> interval(6,7)
res0: Long = 5000
Итак, мы получили наш ответ! 7^7 является первым, 7^5007 - вторым, 7^10007 - третьим и т. Д.
Поскольку это общее, мы можем попробовать другие ответы ... 11^11 = 285311670611 (8-значный номер). Давайте посмотрим на интервале:
scala> interval(12,11)
res1: Long = 50000000000
Таким образом, это говорит о том, что 11^50000000007 является следующее число после 11^11 с тем же начальным набором из 12 цифр. Проверьте вручную, если вам интересно!
Давайте также проверить с помощью 3^3 - какова следующая мощность 3, десятичное расширение которой заканчивается на 27?
scala> interval(2,3)
res2: Long = 20
Должно быть 3^23. Проверка:
scala> List.fill(23)(3L).reduceLeft((l,r) => {println(l*r) ; l*r})
9
27
81
243
729
2187
6561
19683
59049
177147
531441
1594323
4782969
14348907
43046721
129140163
387420489
1162261467
3486784401
10460353203
31381059609
94143178827
Yup!
(Switched код в правках использовать BigInt поэтому он может обрабатывать произвольные числа цифр. Код не обнаруживает вырожденные случаи, хотя, поэтому убедитесь, что вы используете штрих для власти ....)
Можете ли вы показать свой код? –
Вы проверили Project Euler: http://projecteuler.net/ – Guru
@Guru Есть ли у Project Euler алгоритм для этого? –