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

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.

Related

Solve recurrence relation in which there is a separate relation for even and odd values

Can someone help me how to solve these type of questions? What kind of approach should I follow?
Looking over the question, since you will be asked to
evaluate the recurrence lots of times
for very large inputs,
you will likely need to either
find a closed-form solution to the recurrence, or
find a way to evaluate the nth term of the recurrence in sublinear time.
The question, now, is how to do this. Let's take a look at the recurrence, which was defined as
f(1) = f(2) = 1,
f(n+2) = 3f(n) if n is odd, and
f(n+2) = 2f(n+1) - f(n) + 2 if n is even.
Let's start off by just exploring the recurrence to see if any patterns arise. Something that stands out here - the odd terms of this recurrence only depend on other odd terms in the recurrence. This means that we can imagine trying to split this recurrence into two smaller recurrences: one that purely deals with the odd terms, and one that purely deals with the even terms. Let's have D(n) be the sequence of the odd terms, and E(n) be the sequence of the even terms. Then we have
D(1) = 1
D(n+2) = 3D(n)
We only need to evaluate D on odd numbers, so we can play around with that to see if a pattern emerges:
D(2·0 + 1) = 1 = 30
D(2·1 + 1) = 3 = 31
D(2·2 + 1) = 9 = 32
D(2·3 + 1) = 27 = 33
The pattern here is that D(2n+1) = 3n. And hey, that's great news! That means that we have a direct way of computing D(2n+1).
With that in mind, notice that E(n) is defined as
E(2) = 1 = D(1)
E(n+2) = 2D(n+1) - E(n) + 2
Remember that we know the exact value of D(n+1), which is going to make our lives a lot easier. Let's see what happens if we iterate on this recurrence a bit. For example, notice that
E(8)
= 2D(7) - E(6) + 2
= 2D(7) + 2 - (2D(5) - E(4) + 2)
= 2D(7) - 2D(5) + E(4)
= 2D(7) - 2D(5) + (2D(3) - E(2) + 2)
= 2D(7) - 2D(5) + 2D(3) + 2 - D(1)
= 2D(7) - 2D(5) + 2D(3) - D(1) + 2
Okay... that's really, really interesting. It seems like we're getting an alternating sum of the D recurrence, where we alternate between including and excluding 2. At this point, if I had to make a guess, I'd say that the way to solve this recurrence is going to be to think about subdividing the even case further into cases where the inputs are 2n for an even n and 2n for an odd n. In fact, notice that if the input is 2n for even n, then there won't be a +2 term at the end (all the +2's are balanced out by -2's), whereas if the input is odd, then there will be a +2 term at the end (all the +2's are balanced out by -2's).
Now, let's turn to a different aspect of the problem. You weren't asked to query for individual terms of the recurrence. You were asked to query for the sum of the recurrence, evaluated over a range of inputs. The fact that we're getting alternating sums and differences of the D terms here is really, really interesting. For example, what is f(10) + f(11) + f(12)? Well, we know that f(11) = D(11), which we can compute directly. And we also know that f(10) and f(12) are E(10) and E(12). And watch what happens if we evalute E(10) + E(12):
E(10) + E(12)
= (D(9) - D(7) + D(5) - D(3) + D(1) + 2) + (D(11) - D(9) + D(7) - D(5) + D(3) - D(1))
= D(11) + (D(9) - D(9)) + (D(7) - D(7)) + (D(5) - D(5)) + (D(3) - D(3)) + (D(1) - D(1)) + 2
= D(11) + 2.
Now that's interesting. Notice that all of the terms have cancelled out except for the D(11) term and the +2 term! More generally, this might lead us to guess that there's some rule about how to simplify E(n+2) + E(n). In fact, there is. Specifically:
E(2n) + E(2n+2) = D(2n+1) + 2
This means that if we're summing up lots of consecutive values in a range, every pair of adjacent even terms will simplify instantly to something of the form D(2n+1) + 2.
There's still some more work to be done here. For example, you'll need to be able to sum up enormous numbers of D(n) terms, and you'll need to factor in the effects of all the +2 terms. I'll leave those to you to figure out.
One hint: all the values you're asked to return are modulo some number P. This means that the sequence of values 0, D(1), D(1) + D(3), D(1) + D(3) + D(5), D(1) + D(3) + D(5) + D(7), etc. eventually has to reach 0 again (mod P). You can both compute how many terms have to happen before this occurs and write down all the values encountered when doing this by just computing these values explicitly. That will enable you to sum up huge numbers of consecutive D terms in a row - you can mod the number of terms by the length of the cycle, then look up the residual sum in the table.
Hope this helps!

Algorithm: constrained XOR of numbers within a range

Let us say we are given a number n.
We need to find the number of values S ^ (S+n) lying in the range [L, R].
(Where S is any non-negative integer and ^ is the bitwise xor operator).
I can easily do this if n is power of two (they have a very useful pattern)
I am not sure how to solve this for any general n.
Any suggestions?
EDIT:
n is also a non-negative integer.
n, L, R are all less than 10^18.
This was a programming question in some practice test which i gave sometime back, i just remembered this seeing a similar question in StackOverflow today.
EDIT 2:
Explaining with an example,
say n = 1.
Then we know that S ^ (S + 1) will always have a binary representation of all ones. eg: 1,3,7,...
So solving this is easy we just have to count the number of such numbers within the Range [L,R] it is quite simple.
For n = any power of 2 similar methods work. But i have no idea what to do if n is not a power of 2.
Let C(n) be the (infinite) set of numbers that can be written as S ^ (S + n) for some S.
We have the following recurrence relations on the sets C(n):
If n = 2k is even, then C(n) = {2x : x in C(k)};
If n = 2k + 1 is odd, then C(n) = {2x + 1 : x in C(k)} union {2x + 1 : x in C(k + 1)}.
An algorithm can be deduced from these relations. More precisely, a pair (C(n), C(n + 1)) can be deduced from (C(n / 2), C(n / 2 + 1)). Note that the union above is really a disjoint union, because every element in C(n) has the same parity as n, hence C(k) and C(k + 1) do not intersect.
Proof of the recurrence relations:
Simply look at the last binary digits of n and S.

How to do recurrence relations?

nSo we were taught about recurrence relations a day ago and we were given some codes to practice with:
int pow(int base, int n){
if (n == 0)
return 1;
else if (n == 1)
return base;
else if(n%2 == 0)
return pow(base*base, n/2);
else
return base * pow(base*base, n/2);
}
The farthest I've got to getting its closed form is T(n) = T(n/2^k) + 7k.
I'm not sure how to go any further as the examples given to us were simple and does not help that much.
How do you actually solve for the recurrence relation of this code?
Let us count only the multiplies in a call to pow, denoted as M(N), assuming they dominate the cost (a nowadays strongly invalid assumption).
By inspection of the code we see that:
M(0) = 0 (no multiply for N=0)
M(1) = 0 (no multiply for N=1)
M(N), N>1, N even = M(N/2) + 1 (for even N, recursive call after one multiply)
M(N), N>1, N odd = M(N/2) + 2 (for odd N, recursive call after one multiply, followed by a second multiply).
This recurrence is a bit complicated by the fact that it handles differently the even and odd integers. We will work around this by considering sequences of even or odd numbers only.
Let us first handle the case of N being a power of 2. If we iterate the formula, we get M(N) = M(N/2) + 1 = M(N/4) + 2 = M(N/8) + 3 = M(N/16) + 4. We easily spot the pattern M(N) = M(N/2^k) + k, so that the solution M(2^n) = n follows. We can write this as M(N) = Lg(N) (base 2 logarithm).
Similarly, N = 2^n-1 will always yield odd numbers after divisions by 2. We have M(2^n-1) = M(2^(n-1)-1) + 2 = M(2^(n-2)-1) + 4... = 2(n-1). Or M(N) = 2 Lg(N+1) - 2.
The exact solution for general N can be fairly involved but we can see that Lg(N) <= M(N) <= 2 Lg(N+1) - 2. Thus M(N) is O(Log(N)).

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

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.

Dynamic programming approximation

I am trying to calculate a function F(x,y) using dynamic programming. Functionally:
F(X,Y) = a1 F(X-1,Y)+ a2 F(X-2,Y) ... + ak F(X-k,Y) + b1 F(X,Y-1)+ b2 F(X,Y-2) ... + bk F(X,Y-k)
where k is a small number (k=10).
The problem is, X=1,000,000 and Y=1,000,000. So it is infeasible to calculate F(x,y) for every value between x=1..1000000 and y=1..1000000. Is there an approximate version of DP where I can avoid calculating F(x,y) for a large number of inputs and still get accurate estimate of F(X,Y).
A similar example is string matching algorithms (Levenshtein's distance) for two very long and similar strings (eg. similar DNA sequences). In such cases only the diagonal scores are important and the far-from-diagonal entries do not contribute to the final distance. How do we avoid calculating off-the-diagonal entries?
PS: Ignore the border cases (i.e. when x < k and y < k).
I'm not sure precisely how to adapt the following technique to your problem, but if you were working in just one dimension there is an O(k3 log n) algorithm for computing the nth term of the series. This is called a linear recurrence and can be solved using matrix math, of all things. The idea is to suppose that you have a recurrence defined as
F(1) = x_1
F(2) = x_2
...
F(k) = x_k
F(n + k + 1) = c_1 F(n) + c_2 F(n + 1) + ... + c_k F(n + k)
For example, the Fibonacci sequence is defined as
F(0) = 0
F(1) = 1
F(n + 2) = 1 x F(n) + 1 x F(n + 1)
There is a way to view this computation as working on a matrix. Specifically, suppose that we have the vector x = (x_1, x_2, ..., x_k)^T. We want to find a matrix A such that
Ax = (x_2, x_3, ..., x_k, x_{k + 1})^T
That is, we begin with a vector of terms 1 ... k of the sequence, and then after multiplying by matrix A end up with a vector of terms 2 ... k + 1 of the sequence. If we then multiply that vector by A, we'd like to get
A(x_2, x_3, ..., x_k, x_{k + 1})^T = (x_3, x_4, ..., x_k, x_{k + 1}, x_{k + 2})
In short, given k consecutive terms of the series, multiplying that vector by A gives us the next term of the series.
The trick uses the fact that we can group the multiplications by A. For example, in the above case, we multiplied our original x by A to get x' (terms 2 ... k + 1), then multiplied x' by A to get x'' (terms 3 ... k + 2). However, we could have instead just multiplied x by A2 to get x'' as well, rather than doing two different matrix multiplications. More generally, if we want to get term n of the sequence, we can compute Anx, then inspect the appropriate element of the vector.
Here, we can use the fact that matrix multiplication is associative to compute An efficiently. Specifically, we can use the method of repeated squaring to compute An in a total of O(log n) matrix multiplications. If the matrix is k x k, then each multiplication takes time O(k3) for a total of O(k3 log n) work to compute the nth term.
So all that remains is actually finding this matrix A. Well, we know that we want to map from (x_1, x_2, ..., x_k) to (x_1, x_2, ..., x_k, x_{k + 1}), and we know that x_{k + 1} = c_1 x_1 + c_2 x_2 + ... + c_k x_k, so we get this matrix:
| 0 1 0 0 ... 0 |
| 0 0 1 0 ... 0 |
A = | 0 0 0 1 ... 0 |
| ... |
| c_1 c_2 c_3 c_4 ... c_k |
For more detail on this, see the Wikipedia entry on solving linear recurrences with linear algebra, or my own code that implements the above algorithm.
The only question now is how you adapt this to when you're working in multiple dimensions. It's certainly possible to do so by treating the computation of each row as its own linear recurrence, then to go one row at a time. More specifically, you can compute the nth term of the first k rows each in O(k3 log n) time, for a total of O(k4 log n) time to compute the first k rows. From that point forward, you can compute each successive row in terms of the previous row by reusing the old values. If there are n rows to compute, this gives an O(k4 n log n) algorithm for computing the final value that you care about. If this is small compared to the work you'd be doing before (O(n2 k2), I believe), then this may be an improvement. Since you're saying that n is on the order of one million and k is about ten, this does seem like it should be much faster than the naive approach.
That said, I wouldn't be surprised if there was a much faster way of solving this problem by not proceeding row by row and instead using a similar matrix trick in multiple dimensions.
Hope this helps!
Without knowing more about your specific problem, the general approach is to use a top-down dynamic programming algorithm and memoize the intermediate results. That way you will only calculate the values that will be actually used (while saving the result to avoid repeated calculations).

Resources