代码之家  ›  专栏  ›  技术社区  ›  Ravi Gupta

需要设计一个数字运算算法

  •  10
  • Ravi Gupta  · 技术社区  · 16 年前

    我该怎么办?我得到的结果非常慢,它不断乘以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);}
                }
    

    CPU听起来像一个高压锅,但无法得到答案:(

    6 回复  |  直到 16 年前
        1
  •  8
  •   Sklivvz    8 年前

    模10^6相乘。看到这个了吗 Lua code .

    local x=1
    for i=1,100000 do
            x=(x*7) % 1e6
            if x==823543 then print(i) end
    end
    
        3
  •  4
  •   BioGeek    16 年前

    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
    
        4
  •  2
  •   High Performance Mark    16 年前

    与其说是回答,不如说是暗示:

    观察7的幂的最右边数字的模式是1,7,9,3,1,7,9,3,1,7,。。。所以你只需要从3次方开始,每4次方产生7。进一步研究可能会发现两个(三,四,…)最右边的数字的模式,但我还没有为您研究它们。

    为一些非常大的数字做好准备, 数学软件

    我猜这回答了你的问题——一个更快的方法是在SO上发布,然后等待有人告诉你答案!如果你不喜欢SO算法,你甚至可以试试Wolfram Alpha。

        5
  •  2
  •   Rex Kerr    16 年前

    费马的小定理方法是一种数学上合理的方法,只需反复乘以7模10^6是最简单的代码,但是你可以采用另一种方法,计算效率高(但需要更复杂的代码)。首先,注意当乘以7时 数字仅取决于 最后的

    7  (4)9  (6)3  (2)1 (0)7 ...
    

    二 当上升7^4时,数字总是相同的。

    最后三个呢?那么,7^3=343,7^4以401结尾,所以我们得到mod 1000

    343 543 743 943 143 343
    

    我们在#2(543)列中得到了前三位数字,我们看到序列每5次重复一次,所以我们应该从那里上升到7^20。

    我们可以一次又一次地玩这个把戏:找出下一个数字块重复的频率,找出该块中正确的子序列,然后不是乘以7而是乘以7^n。

    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位数字(即mod 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位数初始集。如果你好奇的话,用手检查一下!

    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
    

    是的!


        6
  •  1
  •   Ritsaert Hornstra    16 年前

    另一个提示:您只对最后N个数字感兴趣:您可以执行模10^N的计算,并将结果很好地拟合为整数

    推荐文章