Is there any algorithm to improve my code? - algorithm

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.

Related

In how many ways can you construct an array of size N such that the product of any pair of consecutive elements in not greater than M?

Every element is an integer and should have a value of at least 1.
Constraints: 2 ≤ N ≤ 1000 and 1 ≤ M ≤ 1000000000.
We need to find the answer modulo 1000000007
May be we can calculate dp[len][type][typeValue], where type have only two states:
type = 0: this is means, that last number in sequence with length len equal or smaller than sqrt(M). And this number we save in typeValue
type = 1: this is means, that last number in sequence bigger than sqrt(M). And we save in typeValue number k = M / lastNumber (rounded down), which not greater than sqrt(M).
So, this dp have O(N sqrt(M)) states, but how can we calculate each 'cell' of this dp?
Firstly, consider some 'cell' dp[len][0][number]. This value can calculate as follows:
dp[len][0][number] = sum[1 <= i <= sqrt(M)] (dp[len - 1][0][i]) + sum[number <= i <= sqrt(M)] (dp[len - 1][1][i])
Little explanation: beacuse type = 0 => number <= sqrt(M), so we can put any number not greater than sqrt(M) next and only some small number greater.
For the dp[len][1][number] we can use next equation:
dp[len][1][k] = sum[1 <= i <= k] (dp[len - 1][0][i] * cntInGroup(k)) where cntInGroup(k) - cnt numbers x such that M / x = k
We can simply calculate cntInGroups(k) for all 1 <= k <= sqrt(M) using binary search or formulas.
But another problem is that out algorithm needs O(sqrt(M)) operations so result asymptotic is O(N M). But we can improve that.
Note that we need to calculate sum of some values on segments, which were processed on previous step. So, we can precalculate prefix sums in advance and after that we can calculate each 'cell' of dp in O(1) time.
So, with this optimization we can solve this problem with asymptotic O(N sqrt(M))
Here is an example for N = 4, M = 10:
1 number divides 10 into 10 equal parts with a remainder less than the part
1 number divides 10 into 5 equal parts with a remainder less than the part
1 number divides 10 into 3 equal parts with a remainder less than the part
2 numbers divide 10 into 2 equal parts with a remainder less than the part
5 numbers divide 10 into 1 part with a remainder less than the part
Make an array and update it for each value of n:
N 1 1 1 2 5
----------------------
2 10 5 3 2 1 // 10 div 1 ; 10 div 2 ; 10 div 3 ; 10 div 5,4 ; 10 div 6,7,8,9,10
3 27 22 18 15 10 // 10+5+3+2*2+5*1 ; 10+5+3+2*2 ; 10+5+3 ; 10+5 ; 10
4 147 97 67 49 27 // 27+22+18+2*15+5*10 ; 27+22+18+2*15 ; 27+22+18 ; 27+22 ; 27
The solution for N = 4, M = 10 is therefore:
147 + 97 + 67 + 2*49 + 5*27 = 544
My thought process:
For each number in the first array position, respectively, there could be the
following in the second:
1 -> 1,2..10
2 -> 1,2..5
3 -> 1,2,3
4 -> 1,2
5 -> 1,2
6 -> 1
7 -> 1
8 -> 1
9 -> 1
10 -> 1
Array position 3:
For each of 10 1's in col 2, there could be 1 of 1,2..10
For each of 5 2's in col 2, there could be 1 of 1,2..5
For each of 3 3's in col 2, there could be 1 of 1,2,3
For each of 2 4's in col 2, there could be 1 of 1,2
For each of 2 5's in col 2, there could be 1 of 1,2
For each of 1 6,7..10 in col 2, there could be one 1
27 1's; 22 2's; 18 3's; 15 4's; 15 5's; 10 x 6's,7's,8's,9's,10's
Array position 4:
1's = 27+22+18+15+15+10*5
2's = 27+22+18+15+15
3's = 27+22+18
4's = 27+22
5's = 27+22
6,7..10's = 27 each
Create a graph and assign the values from 0 to M to the vertices. An edge exists between two vertices if their product is not greater than M. The number of different arrays is then the number of paths with N steps, starting at the vertex with value 0. This number can be computed using a simple depth-first search.
The question is now whether this is efficient enough and whether it can be made more efficient. One way is to restructure the solution using matrix multiplication. The matrix to multiply with represents the edges above, it has a 1 when there is an edge, a 0 otherwise. The initial matrix on the left represents the starting vertex, it has a 1 at position (0, 0), zeros everywhere else.
Based on this, you can multiply the right matrix with itself to represent two steps through the graph. This means that you can combine two steps to make them more efficient, so you only need to multiply log(N) times, not N times. However, make sure you use known efficient matrix multiplication algorithms to implement this, the naive one will only perform for small M.

How to generate the continuous sequence which sum up equal to N [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Given a number N and generate an Arithmetic Progression having difference of 1 so that after summing up to finite element gives the number N
for example:
For Example:
N=10
1 + 2 + 3 + 4 =10
N=20
2+3+4+5+6 = 20
N=30
4+5+6+7+8 = 30
N < 1000000
Start with sum = 0.
Let 1 be the current number.
Add the current number to the sum.
If sum > N, subtract numbers from the first number added to the sum until sum <= N.
Stop if sum = N (success).
Increase the current number.
Continue from step 3.
You'll just need to remember the first number added to the sum for step 4, which you will increase by one as you subtract it from the sum (thanks Niko).
As an optimization, you can also use a formula (n(n+1)/2) to add numbers in batch rather than adding them one by one (in case N is large).
Example:
N = 30
Sum = 0
Add 1 -> 1
Add 2 -> 3
Add 3 -> 6
Add 4 -> 10
Add 5 -> 15
Add 6 -> 21
Add 7 -> 28
Add 8 -> 36
36 > 30, so:
Subtract 1 -> 35
Subtract 2 -> 33
Subtract 3 -> 30
Done.
Let T be the number
So N(N+1)/2 = T in your first case where N=4
N(N+1)/2 - K(K+1)/2 = T in your second case where N=6 & K=1
N(N+1)/2 - K(K+1)/2 = T in your third case where N=8 & K=3
So you solve for N basically that is by multiplying & reducing you get
N^2 + N - (2T + K^2 + K) = 0
Applying quadratic formula for N that is
N= (-b + sqrt(b^2 - 4ac))/2a
So we get,
N = (-1 +- sqrt(1 + 8T + 4K^2 + 4K))/2
N has to be positive so we can remove the negative case
Therefore N has to be equal to
N = (sqrt(8T + (2k+1)^2) - 1)/2
You can iterate from K=0 till you get a natural number N which will be your answer
Hope it helps, Iam trying to find a better way as iam doing this(appreciate the interesting problem)
Let N = pq where p is an odd positive integer and q is any positive integer.
(1) You can write N as sum of p consecutive integers, with q as the middle value.
(2) And if both p and q are odd (say, q = 2k+1), you can also write N as sum of 2p consecutive integers, with k and k+1 in the middle.
For example, let N = 15 = 5 x 3.
If we choose p=5, then following rule (1) we have 1+2+3+4+5 = 15.
Or by rule (2) we could also write (-3)+(-2)+(-1)+0+1+2+3+4+5+6 = 15.
We can also choose p = 3 to get 4+5+6 = 15 and 0+1+2+3+4+5 = 15 too.
int NumSum(int val)
{
int n = 0, i = 0, j;
while (n != val)
{
n = 0;
j = ++i;
while (n < val)
n += j++;
}
return i;
}
No fancy maths, just the easy way of doing it.. Returns number to start counting from.
This is more of a trick method & i think it might work.
Lets say number is 10 then start a sequence from n/2 that is 5
Now the sequence cannot be
5+6 since 10>11 so we have to work backwards also 5 is the upper limit of numbers we need to consider since numbers like 6+7 etc will exceed 10 so the last number(highest) of the sequence will be 5.
moving backwards 5+4=9 < 10
5+4+3=12 > 10 so remove first element kinda like a queue.
So for 20 we have
start = 20/2 = 10
10 + 9 = 19 -> do nothing
10 + 9 + 8 = 27 -> remove first element that is 10
9 + 8 + 7 = 24 -> remove 9
8 + 7 + 6 = 21 -> remove 8
7 + 6 + 5 = 18 -> do nothing
7 + 6 + 5 + 4 = 22 -> remove 7
6 + 5 + 4 + 3 = 18 -> do nothing
6 + 5 + 4 + 3 + 2 = 20 -> Answer we need
I guess this is a variation to the accepted answer but still thought i could add this as an alternative solution.
First, every odd number is the sum of an AP length 2 because n = floor(n/2) + ceil(n/2).
More interestingly, a number with an odd divisor d is a sum of an AP length d (with difference 1) around n/d. For instance, 30 is divisible by 5, so is the sum of an AP around 6: 30 = 4 + 5 + 6 + 7 + 8.
A number with no odd divisors is a power of 2. While 1 = 0 + 1 and 2 = -1 + 0 + 1 + 2, larger powers are not the sum of any (non-trivial) arithmetic progression. Why? Suppose 2**m = a + (a+1) + .. + (a+k-1). Sum the series = k (2a + k-1) / 2. k must be odd or even, but either choice contradicts the sum being a power of 2.

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.

Adjacent Bit Counts

here is the problem from spoj that states
For a string of n bits x1,x2,x3,...,Xn
the adjacent bit count of the string
(AdjBC(x)) is given by
X1*X2 + X2*X3 + X3*X4 + ... + Xn-1 *
Xn
which counts the number of times a 1
bit is adjacent to another 1 bit. For
example:
AdjBC(011101101) = 3
AdjBC(111101101) = 4
AdjBC(010101010) = 0
and the question is : Write a program which takes as input integers n and k and returns the number of bit strings x of n bits (out of 2ⁿ) that satisfy AdjBC(x) = k.
I have no idea how to solve this problem. Can you help me to solve this ?
Thanks
Often in combinatorial problems, it helps to look at the set of values it produces. Using brute force I calculated the following table:
k 0 1 2 3 4 5 6
n +----------------------------
1 | 2 0 0 0 0 0 0
2 | 3 1 0 0 0 0 0
3 | 5 2 1 0 0 0 0
4 | 8 5 2 1 0 0 0
5 | 13 10 6 2 1 0 0
6 | 21 20 13 7 2 1 0
7 | 34 38 29 16 8 2 1
The first column is the familiar Fibonacci sequence, and satisfies the recurrence relation f(n, 0) = f(n-1, 0) + f(n-2, 0)
The other columns satisfies the recurrence relation f(n, k) = f(n - 1, k) + f(n - 1, k - 1) + f(n - 2, k) - f(n - 2, k - 1)
With this, you can do some dynamic programming:
INPUT: n, k
row1 <- [2,0,0,0,...] (k+1 elements)
row2 <- [3,1,0,0,...] (k+1 elements)
repeat (n-2) times
for j = k downto 1 do
row1[j] <- row2[j] + row2[j-1] + row1[j] - row1[j-1]
row1[0] <- row1[0] + row2[0]
swap row1 and row2
return row2[k]
As a hint you can split it up into two cases: numbers ending in 0 and numbers ending in 1.
def f(n, k):
return f_ending_in_0(n, k) + f_ending_in_1(n, k)
def f_ending_in_0(n, k):
if n == 1: return k == 0
return f(n - 1, k)
def f_ending_in_1(n, k):
if n == 1: return k == 0
return f_ending_in_0(n - 1, k) + f_ending_in_1(n - 1, k - 1)
This gives the correct output but takes a long time to execute. You can apply standard dynamic programming or memoization techniques to get this to perform fast enough.
I am late to the party, but I have a linear time complexity solution.
For me this is more of a mathematical problem. You can read the detailed solution in this blog post written by me. What follows is a brief outline. I wish I could put some LaTeX, but SO doesn't allows that.
Suppose for given n and k, our answer is given by the function f(n,k). Using Beggar's Method, we can arrive at the following formula
f(n,k) = SUM C(k+a-1,a-1)*C(n-k+1-a,a), where a runs from 1 to (n-k+1)/2
Here C(p,q) denotes binomial coefficients.
So to get our answer, we have to calculate both the binomial coefficients for each value of a. We can calculate the binomial table beforehand. This approach will then given our answer in O(n^2) since we have to calculate the table.
We can improve the time complexity by using the recursion formula C(p,q) = (p * C(p-1,q-1))/q to calculate the current value of binomial coefficients from their values in previous loop.
Our final code looks like this:
long long x=n-k, y=1, p=n-k+1, ans=0;
ans += x*y;
for(int a=2; a<=p/2; a++)
{
x = (x*(p-2*a+1)*(p-2*a+2))/(a*(p-a+1));
y = (y*(k+a-1))/(a-1);
ans += x*y;
}
You can find the complete accepted solution in my GitHub repository.

Uncrossed Sequence Calculation

From http://discuss.joelonsoftware.com/default.asp?interview.11.794054.1
The sequence A is defined as follows:
Start with the natural numbers
1,2,3,...
Initialize count = 1;
while(there are uncrossed numbers)
{
pick the first uncrossed number say n.
set A[count] = n.
Cross out the number count+n.
Cross out the number n
Increment count.
}
Give a fast algorithm to determine A[n], given n.
Try getting an algorithm which is polynomial in log n.
Sorry for posting this question.
Apparently this is a famous sequence called Wythoff's sequence and there is a neat formula for A[n] given by A[n] = [n*phi] where [x] = integral part of x and phi is the golden ratio.
To calculate [nphi], we can approximate phi as a ratio of consecutive fibonacci numbers, giving an O(lognloglogn) algorithm. (O(logn) time to do arithmetic on O(log n) bit numbers).
Here is how it starts
1 2 3 4 5 6 7 8 ... A[1] = 1, cross 2
1 X 3 4 5 6 7 8 ... A[2] = 1, cross 3
1 X X 4 5 6 7 8 ... A[3] = 1, cross 4
...
number 1 is never crossed because the least number that can be crossed is 1+1==2.
So there is constant time algorithm: A[n] = 1 for all n.

Resources