Approach for Problems which appeared in 101 Hack June Challenge contest [closed] - algorithm

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I gave 101 Hack June Challenge contest but there were two problems which I wasn't able to solve. Can anyone give me some hint on how to approach these two questions:
Q1. Assignment Problem
Calvin has a math assignment at school where he has to evaluate a lot of expressions. Calvin decides to not to waste much of his time. There are ‘M’ expressions overall. By looking at Susie’s answers, Calvin has figured that the answers to all questions form a non decreasing sequence.
He decides that all his answers are going to be between 1 and ‘N’ (inclusive). He fills his answer sheet with a random non-decreasing sequence of length ‘M’ where each element is between 1 and ‘N’.
Here is the part where the real problem starts for Calvin. He does not want to choose a large value of N, because, he will have a lot of options to choose from. Also, if he chooses a very small value of N, a lot of answers would become equal and the teacher will become suspicious.
If x = max1 ≤ i ≤ N (frequency (i)), frequency (i) being the number of times i occurs in the sequence of ‘M’ values he picked. Calvin wants to find out expected value of x. Help him solve the problem.
For example, if M = 3 & N = 3, the possible sequences are:
1 1 1 (x = 3)
1 1 2 (x = 2)
1 1 3 (x = 2)
1 2 2 (x = 2)
1 2 3 (x = 1)
1 3 3 (x = 2)
2 2 2 (x = 3)
2 2 3 (x = 2)
2 3 3 (x = 2)
3 3 3 (x = 3)
expected value of x = 2.2
Input Format
The first line contains an integer T which refers to the number of test cases. T lines follow, each containing 2 numbers, M and N for the corresponding test cases.
Constraints
T ≤ 15
1 ≤ M ≤ 250
1 ≤ N ≤ 10^9
Output Format
Output T lines, each containing answer to the corresponding test case. Error of upto 10^-3 is allowed.
Sample Input
4
1 5
3 3
2 9
9 6
Sample Output
1.0000000000
2.2000000000
1.2000000000
4.3146853147
Q2. GCD mocktail
The Rebel Alliance and the Galactic Empire are engaged in an epic battle in the skies above Endor. The grand setup has d-dimensional board with each dimension of length ‘N’, (i.e) N x N… (d times). Each cell (i1, i2, …id) has the gcd (i1, i2, …id) written on it.
Now, the game begins. A random integer L is chosen and the first person to sum up the Lth power of each number modulo 30000001 wins the game.
Rebel Alliance needs some help and pings you. If they win, you get a million dollars for it. Can you help?
Input Format
There are several test cases. The first line contains the number of test cases T. Then T test cases follow. Each test case is given in the following format.
N and d are given in the first Line.
Q is given in the second line.
Each of the next Q lines contain an integer L.
Constraints
0 <= T <= 10
1 <= N <= 107
1 <= d <= 1000
0 <= L <= 100
0 <= Q <= 50
Output Format
For each test case, output Q lines, indicating the answer.
Sample Input
3
3 2
4
0
1
2
3
5 1
3
0
1
2
6 3
2
2
3
Sample Output
9
12
20
42
5
15
55
421
975
This are links to problems on website:
Q1. https://www.hackerrank.com/contests/101june13/challenges/assignment
Q2. https://www.hackerrank.com/contests/101june13/challenges/gcd-mocktail
The contest has ended, so I guess it's not cheating by asking some help on Stackoverflow.

For Q2:
Let's start by counting how many times each value appears in such an array:
1 - appears whenever the positions are coprime. This is hard to count directly, so let's leave it out for now.
2 - appears when all the positions are a multiple of 2. How many combinations of numbers from [1, N] are all multiples of 2, allowing repeats? There are N / 2 possibilities for the first value, and as many for all of the other d values, so (N / 2)^d possibilities. However, we have also counted those that are all a LARGER multiple, which would give a larger GCD. So we must subtract those formed from nothing but larger multiples, that is (N / 4)^d + (N / 6)^d + ...
k <= N - can be deduced the same as above. Let num(k) be this value.
Therefore, 1 will appear N^d - num(2) - num(3) - ... times.
So you have to compute the sum:
S = num(1) + num(2) * 2^L + num(3) * 3^L + ...
This gives an O(N^2 * L) or O(N^2 log L) solution if you implement it directly, which is too slow, since N can go up to 10^7. We have to do a lot better.
Let's write out S:
S = N^d - num(2) - num(3) - ...
+ num(2) * 2^L + num(3) * 3^L + ...
= N^d + num(2)(2^L - 1) + num(3)(3^L - 1) + ...
= N^d + [(N / 2)^d - (N / 4)^d - ...](2^L - 1)
+ [(N / 3)^d - (N / 6)^d - ...](3^L - 1)
+ [(N / 4)^d - (N / 8)^d - ...](4^L - 1)
+ ...
A lot of terms repeat themselves, but so far I'm not sure where to go from here. I'll leave this up in case it helps anyone take it further and I'll delete it if someone posts a complete solution.

For Q1, imagine if you knew the function f(N, M, K) giving you the # of ways that a non-decreasing sequence of M integers in the range 1 to N could have at most K repeated. Then f(N, M, K) - f(N, M, K-1) gives you the number that have exactly K repeated. And now we get the exact distribution, giving us the exact answer.
Now f(N, M, K) obviously is 0 if 0 = K and 0 < M. And f(N, 0, 0) is trivially 1. (There is only one empty set.) Add in the fact that f(N, M, K) = f(N, M, K-1) + f(N-1, M-K, K) and we're all set to solve with dynamic programming. (The main challenge is that you're probably going to run out of floating point range if N is a billion, and M is 250...)
I'd have to think about Q2. I have an idea how to do it, but it isn't quite as simple for me.

Related

Is there any algorithm to improve my code?

SEAWEED
You're given k days and n seaweed.
(1 ≤ n ≤ 1000, 1 ≤ k ≤ 10^17)
At the very first day, you have n seaweed at level 1
The next day, that n seaweed will reproduce, every n seaweed at level i will reproduce n*i seaweed at level 1, these level 1 seaweed will start reproduce after the day end.
Every seaweed at level i will become level i+1.
After k days, return the total number of seaweed
(im very sorry, if you dont understand the problem, i'm very bad at translating)
EXAMPLE:
INPUT : 3 3
OUTPUT : 39
EXPLANATION:
DAY 0 : 3 SEAWEED
DAY 1 : 3 Level 1 , 3 Level 2 ...
Total seaweed at day 1 = 6
DAY 2 : 3 + 3 * 2 Level 1 (there are 3 level 1 and 3 level 2, so 3 * 1 + 3 * 2 = 9), 3 Level 2 , 3 Level 3
Total seaweed at day 2 = 15
DAY 3: 9 + 3 * 2 + 3 * 3 = 24 (at day 2 there is 9 level 1, 3 level 2 and 3 level 3) Level 1 , 3 + 3*2 = 9 Level 2 , 3 Level 3 , 3 Level 4
Total seaweed at day 3 = 39
TOTAL OF SEAWEED : 39
Can you help me find any algorithm for this problem? and shorten my problem into one sentence
My code doesn't seem so fast
Here's my code for the problem:
def solver(n,k):
storage = [n]
for i in range(k):
reproduction = 0
for j in range(len(storage)):
reproduction += storage[j]*(j+1)
storage = [reproduction] + storage
return sum(storage)%(10**9+7)
Some more test case:
INPUT : n = 4, k = 3
OUTPUT : 52
INPUT : n = 5, k = 5
OUTPUT : 445
Solution might be expressed through Fibonacci numbers:
solver(n,k) = n*Fib(2*k+1)
and Fibonacci numbers for extremely high k values (using modulo 10**9+7) might be calculated with matrix exponentiation method here
The first insight is that the function is linear in n. You can imagine each of the n initial seaweed plants as a separate lineage; their descendants do not interfere with each other, so if you double n, you double the answer. So if you solve f(1, k) then you can get f(n, k) simply by multiplying by n. You could -- by some slow calculation -- make a table of values of f(1, k) for many values of k, then compute f(n, k) for any (n, k) that is requested.
The second insight is to work out e.g. f(1, 5) on paper and see the patterns in the numbers. If you are a mathematician at heart, you will recognise some terms from the Fibonacci sequence. (If you are really a mathematician at heart, you will prove the pattern.) Then you can write the formula for f(n, k), and some fast code to calculate it.

Finding the amount of combination of three numbers in a sequence which fulfills a specific requirement

The question is, given a number D and a sequence of numbers with amount N, find the amount of the combinations of three numbers that have a highest difference value within it that does not exceed the value D. For example:
D = 3, N = 4
Sequence of numbers: 1 2 3 4
Possible combinations: 1 2 3 (3-1 = 2 <= D), 1 2 4 (4 - 1 = 3 <= D), 1 3 4, 2 3 4.
Output: 4
What I've done: link
Well my concept is: iterate through the whole sequence of numbers and find the smallest number that exceeds the D value when subtracted to the current compared number. Then, find the combinations between those two numbers with the currently compared number being a fixed value (which means combination of n [numbers between the two numbers] taken 2). If even the biggest number in the sequence subtracted with the currently compared number does not exceed D, then use a combination of the whole elements taken 3.
N can be as big as 10^5 with the smallest being 1 and D can be as big as 10^9 with the smallest being 1 too.
Problem with my algorithm: overflow occurs when I do a combination of the 1st element and 10^5th element. How can I fix this? Is there a way to calculate that large amount of combination without actually doing the factorials?
EDIT:
Overflow occurs when worst case happens: currently compared number is still in index 0 while all other numbers, when subtracted with the currently compared number, is still smaller than D. For example, the value of number at index 0 is 1, the value of number at index 10^5 is 10^5 + 1 and D is 10^9. Then, my algorithm will attempt to calculate the factorial of 10^5 - 0 which then overflows. The factorial will be used to calculate the combination of 10^5 taken 3.
When you seek for items in value range D in sorted list, and get index difference M, then you should calculate C(M,3).
But for such combination number you don't need to use huge factorials:
C(M,3) = M! / (6 * (M-3)!) = M * (M-1) * (M-2) / 6
To diminish intermediate results even more:
A = (M - 1) * (M - 2) / 2
A = (A * M) / 3
You didn't add the C++ tag to your question, so let me write the answer in Python 3 (it should be easy to translate it to C++):
N = int(input("N = "))
D = int(input("D = "))
v = [int(input("v[{}] = ".format(i))) for i in range (0, N)]
count = 0
i, j = 0, 1
while j + 1 < N:
j += 1
while v[j] - v[i] > D:
i += 1
d = j - i
if d >= 2:
count += (d - 1) * d // 2 # // is the integer division
print(count)
The idea is to move up the upper index of the triples j, while dragging the lower index i at the greatest distance j-i=d where v[j]-v[i]<=D. For each i-j pair, there are 1+2+3+...+d-1 possible triples keeping j fixed, i.e., (d-1)*d/2.

Analyze the run time of a nested for loops algorithm

Say i have the following code
def func(A,n):
for i = 0 to n-1:
for k = i+1 to n-1:
for l = k+1 to n-1:
if A[i]+A[k]+A[l] = 0:
return True
A is an array, and n denotes the length of A.
As I read it, the code checks if any 3 consecutive integers in A sum up to 0. I see the time complexity as
T(n) = (n-2)(n-1)(n-2)+O(1) => O(n^3)
Is this correct, or am I missing something? I have a hard time finding reading material about this (and I own CLRS)
You have the functionality wrong: it checks to see whether any three elements add up to 0. To improve execution time, it considers them only in index order: i < k < j.
You are correct about the complexity. Although each loop takes a short-cut, that short-cut is merely a scalar divisor on the number of iterations. Each loop is still O(n).
As for the coding, you already have most of it done -- and Stack Overflow is not a coding service. Give it your best shot; if that doesn't work and you're stuck, post another question.
If you really want to teach yourself a new technique, look up Python's itertools package. You can use this to generate all the combinations in triples. You can then merely check sum(triple) in each case. In fact, you can use the any method to check whether any one triple sums to 0, which could reduce your function body to a single line of Python code.
I'll leave that research to you. You'll learn other neat stuff on the way.
Addition for OP's comment.
Let's set N to 4, and look at what happens:
i = 0
for k = 1 to 3
... three k loop
i = 1
for k = 2 to 3
... two k loops
i = 2
for k = 3 to 3
... one k loop
The number of k-loop executions is the "triangle" number of n-1: 3 + 2 + 1. Let m = n-1; the formula is T(m) = m(m-1)/2.
Now, you propagate the same logic to the l loops. You run T(k) loops on l for k= 1, 2, 3. If I recall, this third-order "pyramid" formula is P(m) = m(m-1)(m-2)/6.
In terms of n, this is (n-1)(n-2)(n-3)/6 loops on l. When you multiply this out, you get a straightforward cubic formula in n.
Here is the sequence for n=5:
0 1 2
0 1 3
0 1 4
change k
0 2 3
0 2 4
change k
0 3 4
change k
change k
change l
1 2 3
1 2 4
change k
1 3 4
change k
change k
change l
2 3 4
BTW, l is a bad variable name, easily confused with 1.

Largest divisor such that two numbers divided by it round to the same value?

I've got an algorithm that can be interpreted as dividing up the number line into an equal number of chunks. For simplicity, I'll stick with [0,1), it will be divided up like so:
0|----|----|----|----|1
What I need to do is take a range of numbers [j,k) and find the largest number of chunks, N, up to some maximum M, that will divide up the number line so that [j,k) still all fall into the same "bin". This is trickier than it sounds, as the range can straddle a bin like so:
j|-|k
0|----|----|----|----|1
So that you may have to get to quite a low number before the range is entirely contained. What's more, as the number of bins goes up, the range may move in and out of a single bin, so that there's local minima.
The obvious answer is to start with M bins, and decrease the number until the range falls into a single bin. However, I'd like to know if there's a faster way than enumerating all possible divisions, as my maximum number can be reasonable large (80 million or so).
Is there a better algorithm for this?
Here I would like to give another heuristic, which is different from btilly's.
The task is to find integers m and n such that m / n <= j < k <= (m + 1) / n, with n as big as possible (but still under M).
Intuitively, it is preferable that the fraction m / n is close to j. This leads to the idea of using continued fractions.
The algorithm that I propose is quite simple:
calculate all the continued fractions of j using minus signs (so that the fractions are always approching j from above), until the denominator exceeds M;
for each such fraction m / n, find the biggest integer i >= 0 such that k <= (m * i + 1) / (n * i) and n * i <= M, and replace the fraction m / n with (m * i) / (n * i);
among all the fractions in 2, find the one with biggest denominator.
The algorithm is not symmetric in j and k. Hence there is a similar k-version, which in general should not give the same answer, so that you can choose the bigger one from the two results.
Example: Here I will take btilly's example: j = 0.6 and k = 0.65, but I will take M = 10.
I will first go through the j-procedure. To calculate the continued fraction expansion of j, we compute:
0.6
= 0 + 0.6
= 0 + 1 / (2 - 0.3333)
= 0 + 1 / (2 - 1 / (3 - 0))
Since 0.6 is a rational number, the expansion terminates in fintely many steps. The corresponding fractions are:
0 = 0 / 1
0 + 1 / 2 = 1 / 2
0 + 1 / (2 - 1 / 3) = 3 / 5
Computing the corresponding i values in step 2, we replaces the three factions with:
0 / 1 = 0 / 1
1 / 2 = 3 / 6
3 / 5 = 6 / 10
The biggest denominator is given by 6 / 10.
Continue with the example above, the corresponding k-procedure goes as follows:
0.65
= 1 - 0.35
= 1 - 1 / (3 - 0.1429)
= 1 - 1 / (3 - 1 / (7 - 0))
Hence the corresponding fractions:
1 = 1 / 1
1 - 1 / 3 = 2 / 3
1 - 1 / (3 - 1 / 7) = 13 / 20
Passing step 2, we get:
1 / 1 = 2 / 2
2 / 3 = 6 / 9
13 / 20 = 0 / 0 (this is because 20 is already bigger than M = 10)
The biggest denominator is given by 6 / 9.
EDIT: experimental results.
To my surprise, the algorithm works better than I thought.
I did the following experiment, with the bound M ignored (equivalently, one can take M big enough).
In every round, I generate a pair (j, k) of uniformly distributed random numbers in the inteval [0, 1) with j < k. If the difference k - j is smaller than 1e-4, I discard this pair, making this round ineffective. Otherwise I calculate the true result trueN using naive algorithm, and calculate the heuristic result heurN using my algorithm, and add them to statistic data. This goes for 1e6 rounds.
Here is the result:
effective round = 999789
sum of trueN = 14013312
sum of heurN = 13907575
correct percentage = 99.2262 %
average quotient = 0.999415
The correct percentage is the percentage of effective rounds such that trueN is equal to heurN, and the average quotient is the average of the quotient heurN / trueN for all effective rounds.
Thus the method gives the correct answer in 99%+ cases.
I also did experiments with smaller M values, and the results are similar.
The best case for the bin size must be larger than k-j.
Consider the number line segments [0..j]and [k..1). If we can divide both of the partial segments into parts using the same bin size, we should be able to solve the problem.
So if we consider gcd((j-0)/(k-j), (1-k)/(k-j)), (where we use the greatest-integer-function after the division), we should be able to get a good estimate, or the best value. There are corner cases: if (k-j) > j or (k-j) > (1-k), the best value is 1 itself.
So a very good estimate should be min(1, (k-j) * gcd((j-0)/(k-j), (1-k)/(k-j)))
Let's turn this around a bit.
You'd like to find m, n as large as you can (though n < M) with m/n close to but less than j and k <= (m+1)/n.
All promising candidates will be on the https://en.wikipedia.org/wiki/Stern%E2%80%93Brocot_tree. Indeed you'll get a reasonably good answer just walking the Stern-Brocot tree to find the last "large rational" fitting your limit just below j whose top is at k or above.
There is a complication. Usually the tree converges quickly. But sometimes the Stern-Brocot tree has long sequences with very small gaps. For example the sequence to get to 0.49999999 will include 1/3, 2/5, 3/7, 4/9, ... We always fall into those sequences when a/b < c/d, then we take the median (a+c)/(b+d) and then we walk towards one side, so (a+i*c)/(b+i*d). If you're clever, then rather than walking the whole sequence you can just do a binary search for the right power of i to use.
The trick to that cleverness is to view your traversal as:
Start with 2 "equal" fractions.
Take their median. If that exceeds M then I'm done. Else figure out which direction I am going from that.
Try powers of 2 in (a+i*c)/(b+i*d) until I know what range i is in for my range and M conditions.
Do binary search to find the last i that I can use.
(a+i*c)/(b+i*d) and (a+i*c+c)/(b+i*d+d) are my two new equal fractions. Go back to the first step.
The initial equal fractions are, of course, 0/1 and 1/1.
This will always find a decent answer in O(log(M)) operations. Unfortunately this reasonably good answer is NOT always correct. Consider the case where M = 3, j=0.6 and k=0.65. In this case the heuristic would stop at 1/2 while the actual best answer is 1/3.
Another way that it can fail is that it only finds reduced answers. In the above example if M was 4 then it still thinks that the best answer is 1/2 when it is actually 1/4. It is easy to handle this by testing whether a multiple of your final answer will work. (That step will improve your answer a fixed, but reasonably large, fraction of the time.)

Algorithm task based on a variation of Fibonacci sequence [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Being given parameters C and M, help decrypt a list of encrypted
integers. The former parameter is used for generating {a_n} and {s_n}
sequences, defined as follows:
a_1 = a_2 = 1
forall n>=1: a_(n+2) = C * a_(n+1) + a_n
forall n: s_n = a_1 + a_2 + a_3 + ... + a_n
The ciphertext consists of T natural numbers. Each of them encrypts
one result number. In order to restore the original x value, it is
necessary to determine the result of the following operation: s_x mod
M
Input: two natural numbers C and M, T denoting number of tests and T
lines consisting of only one x number.
1 <= C, M <= 10^18 1 <= T <= 1000 1 <= x <= 10^18
Example input:
1 10 5 2 3 4 10 1
Example output:
2 4 7 3 1
It's a problem that showed up at the Deadline24 algorithmic competition which took placce this morning and for the love of all that's holy, I couldn't think of any way of pruning the calculations so that you don't have to do 10^18 operations in the worst case scenario.
Any brute force approach is immediately cut out because of that, so is a naive recursion approach. We may note that the sequence is a variation on the Fibonacci sequnece but it doesn't help much as the sequences with C != 1 are divergent from the regular Fibonacci sequence and thus we can't apply any of the approximations like Binet's Fibonacci number formula to calculate F_(n+2) - 1 which would normally be the sum of the first n Fibonacci numbers.
I thought of expressing the terms with C only and applying some fast modpow but it falls short both because it's slow (we still have to calculate the coefficient at each term which is a loop for every power in the final sum) and hard to compute (it looks like there is a pattern but it soon becomes tedious and hard to prove how it will progress).
What's a good way of solving this for max inputs?
We can use matrix exponentiation to get a logarithmic solution:
f(n) = C*f(n - 1) + f(n - 2)
a b f(n)
* = [f(n + 1) f(n)]
c d f(n - 1)
This results in:
a = C
b = 1
c = 1
d = 0
So you can use this matrix to get the n-th term of your function. As for the sum, notice that:
f(n) = Cf(n - 1) + f(n - 2)
f(n - 1) = Cf(n - 2) + f(n - 3)
...
f(3) = Cf(2) + f(1)
=============================== +
s(n) - 2 = C(s(n - 1) - 1) + s(n - 2)
s(n) = Cs(n - 1) + s(n - 2) - (C - 2)
This isn't as nice as what you can do for the Fibonacci numbers (expressing the sum in terms of a single Fibonacci number), but it can be solved by exponentiation by squaring using a similar (3 x 3) matrix to the one of the initial recurrence, which you can find using the same method, and with different starting conditions:
s(1) = 1
s(2) = 2
Let's go through and try to simplify the calculations at each step. First, we should look for a non-recursive formula for a_n. There is a closed form solution for this Recurrence Relationship that gives us a_n = A * r_1**n + B * r_2**n where r_1 and r_2 are the solutions to the equation r**2 = C * r + 1, based on the recurrence relation in the problem. Then we can solve for A and B so that a_1 = a_2 = 1.
Now, we can consider s_n which based on our formula for a_n, and rearranging terms, becomes:
s_n = A * (r_1 + r_1**2 + ... + r_1**n) + B * (r_2 + r_2**2 + ... + r_2**n)
Now, using the formula for the Sum of a Geometric Progression, we get the formula
s_n = A * r_1 * (1 - r_1**n) / (1 - r_1) + B * r_2 * (1 - r_2**n) / (1 - r_2)
This gives you a basic outline for how to proceed. There are a number of things to consider when actually implementing:
The formula for a_n changes if r_1 = r_2. That won't happen in this problem. Why?
If r_1 = 1 or r_2 = 1, the formula calls for dividing by 0.
Integer overflow.
The modular arithmetic at the end.

Resources