Разбор задач 1 тура школы программистов HeadHunter

от автора

Прошел первый раунд отбора участников в школу программистов HeadHunter, анонс на хабре
Где после заполнения анкеты предлагалось решить 5 задачек

В анкете просили заполнить следующие поля:

  • ФИО
  • дату рождения
  • электронную почту
  • город
  • ВУЗ
  • факультет
  • год окончания
  • специальность
  • тему последней курсовой или диплома
  • какие из прослушанных предметов больше всего вам понравились
  • место работы и должность для работающих
  • на каких языках программируете
  • описать опыт разработки
  • участие в олимпиадах и сертификаты
  • почему Вас заинтересовала программа, ожидания от участия

Задача 1

Условие

Для скольки n и k, при условии 1<=n<132, 1<=k<n число сочетаний C(n,k)>1000000?

Полный принтскрин задания

Думаем

Над чем тут думать? 132 это очень мало, подойдет полный перебор, реализуем его на Питоне.
Реализацию числа сочетаний возьмем из пакета 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 синий диск. Во время игры игрок за ход берет случайный диск из мешка, его цвет записывают. После каждого хода взятый диск возвращают в мешок и добавляют туда еще один красный диск.
Игрок платит 1 евро за игру и выигрывает, если в конце игры он достал больше синих дисков, чем красных. Если игра длится 4 хода, вероятность выигрыша равна 11/120, таким образом, максимальный приз, который ведущий игры может назначить за выигрыш в этой игре составляет 10 евро, иначе он начнет нести убытки.
Обратите внимание, что это целое число и оно включает в себя первоначальную оплату участия, таким образом, игрок реально выигрывает 9 евро.
Найдите максимальную целую сумму приза, не делающую игру невыгодной ведущему в игре из 30 ходов?

То же задание принтскрином

Понимаем условие

В процессе игры количество красных шаров увеличивается, значит падает вероятность достать единственный синий. Чтобы выиграть, нужно достать больше половины синих. За первый раз угадать синий вероятность 1/2 за второй раз 1/3, за n-ный раз вероятность достать синий равна 1/(n+1).

Разбираем пример из условия

Если длительность игры равна 4 ходам, получаются вероятности 1/2, 1/3, 1/4, 1/5. Чтобы выиграть, можно ошибиться только 1 раз. Причем в какой из попыток мы ошиблись неважно. Посчитаем, какова вероятность успеха: 1/60+1/40+1/30+1/24+1/120=15/120

Думаем

Факториал 30 число маленькое, опять используем полный перебор. Генератор числа сочетаний возьмем из встроенного в питон пакета 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

Задача 3:

Если в числе все цифры не меньше стоящих слева от них, оно называется увеличивающимся. Пример — 133456. Соответственно, если числа не меньше стоящих справа, оно называется убывающим. Пример: 66420.
Числа, которые не являются ни возрастающими, ни убывающими мы будем называть прыгающими.
Сколько существует пыргающих чисел, меньше 10^75?

Принтскрин задания

Думаем:

Полный перебор долго, а индукция применяется отлично (динамическое программирование)
Действительно, к любому увеличивающемуся числу слева можно приписать от 1 до первой цифры числа включительно, а к любому убывающему справа можно приписать от нуля до последней цифры числа включительно.

Решаем:
# объявляем словари индукции 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$  

Задача 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 780900524347766560369409601397283583731565781613263766310753171005772816606447127796238704640229315255837674837377848165134157698160368949544530968794502543368882016531029514678028439260706408177729197487662072465572674876642154084378757480925617839826591149409430192878644658489021494500819466317586441937981822347486163565795152808072012368235080216554272512192800729666417669829763531411213108494418913118518602993302492226514346776633151914463050060224509695982703686755416142840706010623006936874524452187722869551681108749361294810695099504076646550576016809634068421557376832617580999236289371413151899566524614973575753248715742472176747459972608155732634727630330527033718278452846765174770728172912921167441008174546335351766020470707921356776862494695433732667044761786181261729619777198918422157071750747357444434612359278543575242617905368425489288524399123583290845306893000730480723867599367964989977241039149647013546967023147867695604450552374936008874557855435456223434642380936719467687026632615769316496835506366896848050379321482973448206502401722698140500374496142639625192381119796460488752404250147189479846363428957348179528030884277109256778540767915891043086029025915629061548978311433769206291930634863662192108026152395440631585079728836245987908191549472234398723916120832401441793104897541209034633661071095358336193091746252749026143573 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$   

Говорят, что правильно решены 2 задачи из 5. Одну ошибку знаю, а где другие?

ссылка на оригинал статьи http://habrahabr.ru/post/155015/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *