HeadHunterプログラマースクールの第1ラウンドのタスクの分析

HeadHunterプログラマースクールの参加者の第1回選考が行われました

アンケートに記入した後、5つの問題を解決することが提案されました



アンケートでは、次のフィールドに記入するよう求められました。





タスク1



状態


1 <= n <132、1 <= k <n、組み合わせの数C(n、k)> 1,000,000の場合、nとkの数はいくつですか?

クエストのフルプリントスクリーン




思う


考えるべきことは何ですか? 132これは非常に小さく、完全な検索で十分です。Pythonで実装します。

SciPyパッケージから多くの組み合わせを実装します-多くの点で、これはオープンソースのMatlabです

決める


from scipy.misc import * #     total = 0 for n in range(1,133): for k in range(1,n): if comb(n,k)>1000000: total=total+1 print "Answer: ",total
      
      





実行時間を測定して実行します。

 #:~/hh$ time python 1.py Answer: 7579 real 0m0.530s user 0m0.504s sys 0m0.020s #:~/hh$
      
      





間違いを見つけましたか?
条件からプログラムへの制限が正しく転送されません





タスク2:



状態


バッグには赤と青のディスクが1つずつ入っています。 ゲーム中、プレイヤーはターンごとにバッグからランダムなディスクを取り出し、その色が記録されます。 各移動の後、取り込んだディスクはバッグに戻され、別の赤いディスクがそこに追加されます。

プレーヤーはゲームごとに1ユーロを支払い、ゲームの最後に赤いディスクよりも青いディスクを獲得した場合に勝ちます。 ゲームが4ターン続く場合、勝つ確率は11/120であるため、ゲームのホストがこのゲームで勝つために授与できる最大賞金は10ユーロです。そうでない場合、彼は負け始めます。

これは整数であり、参加の初期支払いが含まれているため、プレーヤーは実際に9ユーロを獲得することに注意してください。

30移動のゲームでリーダーに不利にならない最大賞金総額を見つけますか?

同じprintscreenタスク




状態を理解している


ゲーム中、赤いボールの数が増えます。つまり、青いボールが1つしか得られない可能性が低くなります。 勝つためには、青の半分以上を取得する必要があります。 初めて、青の確率1/2を2回目に1/3と推測します。n回目に、青を取得する確率は1 /(n + 1)です。

条件から例を分析します


ゲームの期間が4ムーブの場合、確率は1 / 2、1 / 3、1 / 4、1 / 5です。 勝つために、あなたは一度だけミスをすることができます。 そして、どの試みにおいても、私たちは間違いを犯しました。 成功の確率を計算しましょう:1/60 + 1/40 + 1/30 + 1/24 + 1/120 = 15/120

思う


階乗30は小さな数字です。ここでも徹底的な検索を使用します。 組み合わせ番号ジェネレーターは Pythonに組み込まれているitertoolsパッケージから取得されます

決める


 import itertools game=30 comb=[] resb=1 for t in range(2,game+2): comb.append(t) resb=resb*t #    print comb resa=0 for q in range(game/2+1,game+1): #      print q,resa,resb #   for t in itertools.combinations(comb,q): #    ca=1 cb=1 for x in t: cb=cb*x tdiv=resb/cb resa=resa+tdiv*ca print game/2+1 print resa,resb #       
      
      







 #:~/hh/article$ time python 2.p [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] 16 0 8222838654177922817725562880000000 17 6014558687904548121004575 8222838654177922817725562880000000 18 6363613319405364461146200 8222838654177922817725562880000000 19 6381128687025974988156255 8222838654177922817725562880000000 20 6381886877953385972148180 8222838654177922817725562880000000 21 6381915085555093961253855 8222838654177922817725562880000000 22 6381915982709887260743580 8222838654177922817725562880000000 23 6381916006925362413306495 8222838654177922817725562880000000 24 6381916007474554489499970 8222838654177922817725562880000000 25 6381916007484879987901695 8222838654177922817725562880000000 26 6381916007485037971122090 8222838654177922817725562880000000 27 6381916007485039887292479 8222838654177922817725562880000000 28 6381916007485039905011334 8222838654177922817725562880000000 29 6381916007485039905128639 8222838654177922817725562880000000 30 6381916007485039905129134 8222838654177922817725562880000000 16 6381916007485039905129135 8222838654177922817725562880000000 real 23m2.424s user 23m0.238s sys 0m0.168s #:~/hh/article$
      
      





23分かかりますが、他の問題も解決します。

分数を最大ゲインに変換する必要があります-分母を分子で除算し、「自己返済」ゲインのサイズを取得します。

 #:~/hh/article$ bc -l bc 1.06.95 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. 8222838654177922817725562880000000/6381916007485039905129135 1288459240.85082818135254719839 ^C (interrupt) use quit to exit. #:~/hh/article$
      
      





最大の前駆体が必要です;それに応じて、整数部分、つまり 1288459240

間違いを見つけましたか?
ここで、間違った確率を考慮しました。 数えるとき、多くの赤から青を選択するだけでなく、多くの中から赤を選択する必要があります。 したがって、プログラムを変更します。

 from datetime import datetime import itertools game=30 comb=[] resb=1 for t in range(2,game+2): comb.append(t) resb=resb*t print comb resa=0 st=datetime.now() for q in range(0,game/2): #         ct=datetime.now() print q, ct-st st=ct for t in itertools.combinations(comb,q): #    q      ta=1 for x in t: ta=ta*(x-1) #      (  1)    -        ,     ,  itertools.combinations      x resa=resa+ta print resa,resb
      
      





答えは発売後15分です





タスク3:



数値に、左側の数値以上のすべての数値が含まれる場合、増加と呼ばれます。 例は133456です。したがって、数値が右側の数値より小さくない場合、減少と呼ばれます。 例:66420。

増加も減少もしていない数値をジャンプと呼びます。

跳ねる数は10 ^ 75未満ですか?

プリントスクリーンクエスト




私たちは考えます:


完全な列挙は長く、帰納法は完全に適用されます(動的プログラミング)

実際、左側の数字を増やす場合は1から数字の最初の桁までを割り当て、右側の数字を減らす場合は0から数字の最後の数字までを割り当てることができます。

私たちは決定します:




 #    a={} #   b={} #   for t in range(0,11): a[1,t]=1 #   -  ,   - () .  -    b[1,t]=1 def snext(tail): global a,b tvar=0 btvar=0 for d in range(0,11): #      a[tail,d]=0 b[tail,d]=0 for d in range(1,10): #    var=0 bvar=0 t=a[tail-1,d] tb=b[tail-1,d] for q in range(1,d+1): var=var+t a[tail,q]=a[tail,q]+t#var tvar=tvar+var for d in range(0,10): #    bvar=0 tb=b[tail-1,d] for q in range(d,10): bvar=bvar+tb b[tail,q]=b[tail,q]+tb btvar=btvar+bvar btvar=btvar-1 print tail,tvar,btvar return [tvar,btvar] start=0 for q in range(2,76): [pa,pb]=snext(q) start=start-pa-pb-9 # ..     , , ....,    -   9 start=start-10 #     print "10^75", start
      
      





長いプログラム出力
 #:~/hh/article$ time python 3.py 2 45 54 3 165 219 4 495 714 5 1287 2001 6 3003 5004 7 6435 11439 8 12870 24309 9 24310 48619 10 43758 92377 11 75582 167959 12 125970 293929 13 203490 497419 14 319770 817189 15 490314 1307503 16 735471 2042974 17 1081575 3124549 18 1562275 4686824 19 2220075 6906899 20 3108105 10015004 21 4292145 14307149 22 5852925 20160074 23 7888725 28048799 24 10518300 38567099 25 13884156 52451255 26 18156204 70607459 27 23535820 94143279 28 30260340 124403619 29 38608020 163011639 30 48903492 211915131 31 61523748 273438879 32 76904685 350343564 33 95548245 445891809 34 118030185 563921994 35 145008513 708930507 36 177232627 886163134 37 215553195 1101716329 38 260932815 1362649144 39 314457495 1677106639 40 377348994 2054455633 41 450978066 2505433699 42 536878650 3042312349 43 636763050 3679075399 44 752538150 4431613549 45 886322710 5317936259 46 1040465790 6358402049 47 1217566350 7575968399 48 1420494075 8996462474 49 1652411475 10648873949 50 1916797311 12565671260 51 2217471399 14783142659 52 2558620845 17341763504 53 2944827765 20286591269 54 3381098545 23667689814 55 3872894697 27540584511 56 4426165368 31966749879 57 5047381560 37014131439 58 5743572120 42757703559 59 6522361560 49280065119 60 7392009768 56672074887 61 8361453672 65033528559 62 9440350920 74473879479 63 10639125640 85113005119 64 11969016345 97082021464 65 13442126049 110524147513 66 15071474661 125595622174 67 16871053725 142466675899 68 18855883575 161322559474 69 21042072975 182364632449 70 23446881315 205811513764 71 26088783435 231900297199 72 28987537150 260887834349 73 32164253550 293052087899 74 35641470150 328693558049 75 39443226966 368136785015 10^75 -3497299458233 real 0m0.070s user 0m0.044s sys 0m0.020s #:~/hh/article$
      
      







間違いを見つけましたか?
分析的に解決します。

増加する数、減少する数を見つけ、ミラー番号の数を引きます。



増加する数の数は、考慮事項から求められます。

セット{0,1,2,3,4,5,6,7,8,9}から複数の数字が与えられた場合、それらを昇順で並べることができます。 返品と注文を考慮せずに骨nサンプル取得します



減少するものを自動的に配置することはできません-ゼロは常に数字の最後、または最初に行くでしょう。 したがって、数値{1,2,3,4,5,6,7,8,9}から選択し、空の場所にゼロを追加します。 空の場所は、すべての数字の前または後にのみ指定できます。それ以外の場合、ジャンプ番号が取得されます。 N個のゼロで、N + 1を途中で配置できます

 import sys from scipy.misc import * game = int(sys.argv[1])# 75 def czero(game,fill): sort=long(round(comb(fill+8,fill),0)) #  fill   1  9 return sort*(game-fill+1) #      def nzero(game): return long(round(comb(game+9,game),0)) #    0  9 zans=0 nans=nzero(game) for fill in range(1,game+1): zans=zans+czero(game,fill) zans=zans+1 print nans, zans ans=nans+zans-(game-1)*9-10 print 10**game-ans
      
      









タスク4:



フィボナッチ数列のメンバーが1369であるようなメンバーの数を見つけます

クエストのフルプリントスクリーン




私たちは考えます:


フィボナッチ数を考慮し、文字列表現に変換して長さを調べます。

私たちは決定します:


 mlen=1369 a1=1 a2=1 ct=2 while len(str(a1+a2))<mlen: a3=a1+a2 a1=a2 a2=a3 ct=ct+1 ct=ct+1 print a3,len(str(a3)),ct
      
      





 #:~/hh$ time python 4.py 1368 6548 real 0m0.183s user 0m0.164s sys 0m0.012s #:~/hh$
      
      





間違いを見つけましたか?
そうではないようです:)



タスク5:



シリーズの最終合計の最後の10桁、1 ^ 1 + 2 ^ 2 + 3 ^ 3 + ... + 1145 ^ 1145を見つけます

フルプリントスクリーンクエスト




私たちは考えます:


1145から1145度までの数字は本当に大きいです。 タスクでは、最後の10桁のみを要求します。これは、モジュラー演算を利用することを意味します。すぐにモジュロを考慮します。

私たちは決定します:


モジュロ度を計算するには、パッケージhttp://userpages.umbc.edu/~rcampbel/Computers/Python/numbthy.htmlを使用します

http://userpages.umbc.edu/~rcampbel/Computers/Python/lib/numbthy.pyをダウンロードして、プログラムフォルダーに配置します。

 import numbthy as np t=0 for i in range(1,1146): t=t+np.powmod(i,i,1000000000000000000000) print t % 10000000000
      
      







 #:~/hh$ time python 5.py 7110603381 real 0m0.029s user 0m0.020s sys 0m0.004s #:~/hh$
      
      







間違いを見つけましたか?
そうではないようです:)





彼らは、5つの問題のうち2つが正しく解決されたと言っています。



All Articles