Я решал проблему Find the min
в hackercup на facebook с помощью python, мой код отлично работает для ввода образцов, но для больших входов (10 ^ 9) для завершения требуется несколько часов.
Итак, возможно ли, что решение этой проблемы невозможно вычислить в течение 6 минут с помощью python? Или могут быть мои подходы слишком плохи?
Описание проблемы:
После отправки смайлов Джон решил играть с массивами. Знаете ли вы, что хакеры любят играть с массивами? Джон имеет индексный массив на основе нуля, m
, который содержит n
неотрицательные целые числа. Однако ему известны только первые k
значения массива, и он хочет выяснить остальное.
Джон знает следующее: для каждого индекса i
, где k <= i < n
, m[i]
- минимальное неотрицательное целое число, которое не содержится в предыдущих *k*
значениях m
.
Например, если k = 3
, n = 4
и известные значения m
равны [2, 3, 0]
, он может выяснить, что m[3] = 1
.
Учитывая первые k
значения m
, вычислите n-ое значение этого массива. (т.е. m[n - 1]
).
Поскольку значения n
и k
могут быть очень большими, мы используем генератор псевдослучайных чисел для вычисления первых значений k
m
. При наличии целых положительных чисел a
, b
, c
и r
известные значения m
можно рассчитать следующим образом:
m[0] = a
m[i] = (b * m[i - 1] + c) % r, 0 < i < k
Ввод
-
Первая строка содержит целое число T (T <= 20), количество тестов случаев.
-
За этим следуют T тестовые примеры, состоящие из двух строк.
-
Первая строка каждого тестового примера содержит целые числа, разделенные пробелом,
n
,k
(1 <= k <= 10^5
,k < n <= 10^9
). -
Вторая строка каждого тестового примера содержит целые 4 пробела
/li >a
,b
,c
,r
(0 <= a, b, c <= 10 ^ 9, 1 <= r <= 10 ^ 9).
Я попробовал два подхода, но оба не смогли вернуть результаты за 6 минут. Здесь мои два подхода:
первый:
import sys
cases=sys.stdin.readlines()
def func(line1,line2):
n,k=map(int,line1.split())
a,b,c,r =map(int,line2.split())
m=[None]*n #initialize the list
m[0]=a
for i in xrange(1,k): #set the first k values using the formula
m[i]= (b * m[i - 1] + c) % r
#print m
for j in range(0,n-k): #now set the value of m[k], m[k+1],.. upto m[n-1]
temp=set(m[j:k+j]) # create a set from the K values relative to current index
i=-1 #start at 0, lowest +ve integer
while True:
i+=1
if i not in temp: #if that +ve integer is not present in temp
m[k+j]=i
break
return m[-1]
for ind,case in enumerate(xrange(1,len(cases),2)):
ans=func(cases[case],cases[case+1])
print "Case #{0}: {1}".format(ind+1,ans)
Во-вторых:
import sys
cases=sys.stdin.readlines()
def func(line1,line2):
n,k=map(int,line1.split())
a,b,c,r =map(int,line2.split())
m=[None]*n #initialize
m[0]=a
for i in xrange(1,k): #same as above
m[i]= (b * m[i - 1] + c) % r
#instead of generating a set in each iteration , I used a
# dictionary this time.
#Now, if the count of an item is 0 then it
#means the item is not present in the previous K items
#and can be added as the min value
temp={}
for x in m[0:k]:
temp[x]=temp.get(x,0)+1
i=-1
while True:
i+=1
if i not in temp:
m[k]=i #set the value of m[k]
break
for j in range(1,n-k): #now set the values of m[k+1] to m[n-1]
i=-1
temp[m[j-1]] -= 1 #decrement it value, as it is now out of K items
temp[m[k+j-1]]=temp.get(m[k+j-1],0)+1 # new item added to the current K-1 items
while True:
i+=1
if i not in temp or temp[i]==0: #if i not found in dict or it val is 0
m[k+j]=i
break
return m[-1]
for ind,case in enumerate(xrange(1,len(cases),2)):
ans=func(cases[case],cases[case+1])
print "Case #{0}: {1}".format(ind+1,ans)
Последний цикл for во втором подходе также может быть записан как:
for j in range(1,n-k):
i=-1
temp[m[j-1]] -= 1
if temp[m[j-1]]==0:
temp.pop(m[j-1]) #same as above but pop the key this time
temp[m[k+j-1]]=temp.get(m[k+j-1],0)+1
while True:
i+=1
if i not in temp:
m[k+j]=i
break
ввод образца:
5
97 39
34 37 656 97
186 75
68 16 539 186
137 49
48 17 461 137
98 59
6 30 524 98
46 18
7 11 9 46
выход:
Case #1: 8
Case #2: 38
Case #3: 41
Case #4: 40
Case #5: 12
Я уже пробовал codereview, но пока никто не ответил.