Необходимо разработать алгоритм хруста числа - PullRequest
10 голосов
/ 11 марта 2010

Я наткнулся на этот вопрос:

7, сила 7 равна 823543. Какая более высокая сила 7 заканчивается 823543?

Как мне это сделать? Тот, который я придумал, очень медленный, он продолжает умножаться на 7 и проверяет последние 6 цифр результата на совпадение.

Я пытался с кодом Лу:

int x=1;
    for (int i=3;i<=100000000;i=i+4){
            x=(x*7)%1000000;
            System.out.println("i="+ i+" x= "+x);
            if (x==823543){
                System.out.println("Ans "+i);}
            }

И процессор звучит как скороварка, но не может получить ответ: (

Ответы [ 6 ]

8 голосов
/ 11 марта 2010

Вы можете использовать обобщение Эйлера из Маленькая теорема Ферма , которая применяется к вашему случаю, говорит, что для любого числа a , которое не делится на два или пять a до степени 400000 равно 1 по модулю 10 ^ 6. Это означает, что 7 ^ 400000 равно единице, а 7 ^ 400007 равно 823543 по модулю 10 ^ 6

.

Могут быть меньшие степени 7, которые также равны одному по модулю 10 ^ 6. Любая такая сила должна быть делителем 400000. Поэтому, если вы ищете все делители 400000, вы должны найти свой ответ.

8 голосов
/ 11 марта 2010

Умножить по модулю 10 ^ 6. Смотрите это код Lua .

local x=1
for i=1,100000 do
        x=(x*7) % 1e6
        if x==823543 then print(i) end
end
4 голосов
/ 11 марта 2010

Решение для перебора в Python:

def check():
    i = 8
    while True:
        if str(7**i)[-6:] == "823543":
            print i, 7**i
            break
        i += 1

if __name__ == "__main__":
  check()

Работает на моей машине чуть более 10 секунд:

$ time python 7\*\*7.py 
5007 25461638709540284156782446957365168367138070393489656084508152816071765490828583739345420574947301301356529652113030016806506783009529977928336772622054260724106711204039012806363481521302203821096274017061906820115931889920385802499836705571461280700786627503189500663279772123190279763997339608040949194040289041117811256914511855302927500076094761237077649092849658261309060277197389760351907599243227298336309204635761799394324969277220810221310805265921431367291459357151617279190810954501590069774137519833706444943573459910208627100504003480684029216932299650285683013274883359754231186580602570771682084721896446416234857382909168309309630688331305154545352580787700878011742720440707156231891841057992434850068501355342227582074144717324718396296563918284728120322255330707786227631084119636101174217518654320128390401231343058708073280898554293777842571799775647325449392944570725467462072394864457569308219294304248413378339223195121800534783732295135735588409249690562213409520783181313960347723827308102920022860541043691808218543350580271593107019737918976365348051012746817678592727727988993175444584453532474156202438866838819565827414970029052602274354173178190323239427022953097424087683011937130778414189673555875258508014323428137406618951161046883845551087123412471364400737145434714864392224194773030522352601143771552489895838728148761974811275894561985163094852437703080985644653666048979901975905667811053289029958524703063742007291722490298429637413913574845245364780928447142275001431370017543206188428912106120676556219532197108435997375879569102044435752697298456147512203108094030745606163915437604076966518127099543894645297945324345093247636119593298654296614887389164509070158924404441687810434488061150620012547321097786493748417764592151734279632949607485719050349385098350202294648324398902047614892248381794929374952059877187100434970751833289677556040879755065563758085919673107576808662549999202791489324437408075089456174056904323973798979207791446889016369166632636035638123394649891606479407561222474471530411700646266636732205895085248823824764170316644547100628119484733814900100986786082211477261114056206393554335903410036064553032366200714266053598548735147707681592574886559888869327771461046450774938490837810526377213647071217152427693219479552580138352651791476758476864761332281826701978038126122728967682552206820425685782165630494478519812498630475776384700259524274670258777572341538755828794632819515842335609785884327007667337426644594091547392441314523035569100326662245947022517857248412004291423280879791576077952474202068318934524092750814844945529148131063116233331840380254781283689084385600858175504170157015630699919186013526052643206240745256569669847298952477441594748635701081031979500954081732722211598460098426985932512920424237248250698541558227081975966598720056015879151923686438360541128221854058867910136449528237543680180470919685862102358708465872395643586424250239281775923511452769821487580471289910257908740451431952197725174728917413539539795856895884961513784804247268727165303942024508367184898248006123651950710237279288601317817391869969699767431782664773248447758526620050588927086506013616563459173620496200348863132442180734592661348887012997849309740799709045762939781801481205704629203758859772476278892928066844445088880207986848424855774325574728566649552154520262460969975214802828263093097997124519153537792591659204109087699977445745067857471581656151077039286563447099850537157044829081400190710358959493358343935904669416958301921942118288210835104022359479660409954097409669785908666166908117346073702337825511531650740900904200220658196171839969860945908503151878488455004283026700303698398069644419655035582904253655945381261383285097911378914794161551292914993411444083214513058414480129560671193659591364146612550890288116403596333209446976453193340267725222134755872075133141618388704912211996423838163706006930973361661094103734887312836613195349528793780496172839376426055357343094188450140671138356505144988151110902047791487250988374130384058324229250761311655685931891857894126054047458969174494155762486464149775147410127618088224310828566286409277000561087588768230619606746804073498788244935099280434916850444895829823543

real    0m10.779s
user    0m10.709s
sys 0m0.024s
2 голосов
/ 11 марта 2010

Метод маленькой теоремы Ферма является математически разумным, и просто перемножать снова и снова на 7 мод 10 ^ 6 - самый простой код, но есть другой подход, который вы можете использовать, который эффективен в вычислительном отношении (но требует более сложного кода). Во-первых, обратите внимание, что при умножении на 7 последняя цифра last зависит только от предыдущей цифры last (т. Е. Мы делаем все в моде 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-й цифрой, а затем умножаем размеры всех колец вместе, чтобы получить промежуток между последовательными степенями, которые имеют одинаковые 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

Да!


(Переключил код в правках, чтобы использовать BigInt, чтобы он мог обрабатывать произвольные числа цифр. Однако код не выявляет вырожденные случаи, поэтому убедитесь, что вы используете простое число для мощности ....)

2 голосов
/ 11 марта 2010

Не столько ответ, сколько подсказка:

Заметьте, что комбинация из самых правых цифр степеней 7 идет 1,7,9,3,1,7,9,3,1,7, ... так что вам нужно только генерировать каждую четвертую степень 7 из 3-й. Дальнейшее изучение может показать образец для двух (трех, четырех, ...) самых правых цифр, но я еще не изучил их для вас.

Будьте готовы к некоторым очень большим числам, Mathematica сообщает, что следующая степень 7 с искомыми крайними правыми цифрами - 5007-я.

Который, я думаю, отвечает на ваш вопрос - более быстрый подход состоит в том, чтобы публиковать сообщения на SO и ждать, пока кто-нибудь скажет вам ответ! Вы даже можете попробовать Wolfram Alpha, если вам не нравится алгоритм SO.

1 голос
/ 11 марта 2010

Еще один совет: вас интересуют только последние N цифр: вы можете выполнять вычисления по модулю 10 ^ N и сохранять результат вписывающимся в целое число

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...