Given a n+1-tuple (a0, a1, ..., an).
We need to calulate F(m, n).
Given:
a0 <= a1 <= ... <= an
F(x, y) = ay * F(x - 1, y) + F(x, y - 1)
F(0, y) = 1 for all y
F(x, 0) = a0x
I was thinking of dp approach but problem i faced is too large 'm' which can be larger than a billion.
Is there any way to solve this out?
I feel this can be converted to a matrix exponentiation problem but not able to figure out how?
I am new to stack overflow and programming too. Any edit suggestions in question and approach/solution for problem will be appreciated.
Your "matrix exponentiation" idea is correct.
Write F(x, _) as a vertical vector. (That is, one entry for each value of y.)
There is a matrix A such that F(x+1, _) = A * F(x, _). Once found, it turns out that F(x+k, _) = A^k * F(x, _).
Now you know F(0, _). You can find A. Then with repeated squaring you can find A^m and now you can answer your question.
Related
My question is similar to this, but instead if the absolute difference is raised to a power 'c' (which will be given as input) is there an algorithm to find the answer?
For example, given A = {a1, a2,...., an} and c it should find an x such that it minimises |a1 − x|^c +|a2 − x|^c +··· +|an − x|^c.
If c = 1 it's the median of the sorted array and if c = 2 it's the average of the array, but I can't find connection between median and average which we can extend to any value of c.
I assume that c is a positive integer.
If it is not an integer, then the fractional powers are hard to calculate. If it is negative, then as x goes to infinity (either way) the result goes to 0, so there is no global minimum. If it is 0, then x does not matter. So a positive integer is the only thing that makes sense.
Now each term is a convex function. The sum of convex functions is itself convex. Convex functions have the following properties. Suppose that x < y < z. If f(x) = f(z) then the global minimum is between them. If f(x) = f(y) = f(z), that's a straight line segment. And finally, if f(y) < min(f(x), f(z)) then the global minimum is between x and z.
This is sufficient for a variation on binary search.
while z - x > some tolerance:
if z-y > y-x:
y1 = (y + z) / 2
if f(y1) < f(y):
(x, y, z) = (y, y1, z)
elif f(y1) = f(y):
(x, y, z) = (y1, (2*y1 + y)/3, y)
else:
(x, y, z) = (y1, y, z)
else:
y1 = (x + y) / 2
if f(y1) < f(y):
(x, y, z) = (x, y1, y)
elif f(y1) = f(y):
(x, y, z) = (y1, (2*y1 + y)/3, y)
else:
(x, y, z) = (y1, y, z)
As this runs, each iteration reduces the size of the interval to at most 3/4 of what it previously was. And therefore you will narrow in on the answer.
If you special case c = 1, you can do even better. The second derivative will be defined everywhere and be a non-decreasing function. This allows you to do a binary search, but guess where in the interval the minimum is expected to be. If you land close, you know which way you're wrong, and can put a much tighter bound on it.
I'm solving a problem and I reduced it to the following one:
Given n points (x1, y1), ..., (xn, yn) (0 <= xi, yi), and two integers A and B (0 <= A, B) I need to find a subset of those points such that:
1) The sum of the x values is at most A (SUM(x) <= A).
2) The sum of the y values is at least B (SUM(y) >= B).
I'm struggling with this problem and I cannot find a solution other than combining. I would appreciate some ideas.
UPD: xi and A are rationals (represented as floats/double). yi and B are integers.
Depending on the distribution and the space available, we could create a "merge sort" segment tree, where the segments divide the X range and the tree array-nodes are sorted by y values. Then test partitions of A such that we can choose multiple xs maxed by the right-bound of each part, choosing the top y values in O(log n) from the segment tree.
So i have this problem: given a set of two dimensional tuples on the form {x,y}, where all x and y are positive integers, decide if it is possible to take out a subset so that:
√( (∑x)² + (∑y)²) = A²
For a positive integer A.
Example, given
[{2,2},{1,4},{1,2}] and A = 5
one solution is {2,2} and {1,2} since 3² + 4² = 5²
It is allowed to reuse the same tuple multiple times.
The goal is th solve this with dynamic programming. I was looking at http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/, a dynamic solution of a subset sum problem; however the difference here is that all the terms are squared and 2d, so i don't believe that method works
There may be faster options, but a simple PD is:
T(X, Y, i): Is it possible to achieve the ∑x = X and ∑y = Y using up to the i-th term?
T(0, 0, 0) = TRUE
T(X, Y, i) = FALSE if X<0 or Y<0 or (i==0 and X!=0 and Y!=0)
T(X, Y, i) = T(X-V[i].X, Y-V[i].Y, i) or T(X, Y, i-1)
Then, scan every pair (X, Y), to find one that X²+Y²=A² and T(X, Y, n) is true (where n is the size of the set).
Here is a non-optimized recursive version just to prove the concept (in Python):
def T(V, x, y, i):
if x==0 and y==0 and i==0: return []
if x<0 or y<0 or i<=0: return None
answer = T(V, x-V[i-1][0], y-V[i-1][1], i)
if answer is not None: return answer + [V[i-1]]
return T(V, x, y, i-1)
def solve(V, A):
for x in range(A):
for y in range(A):
if x*x+y*y==A*A:
answer = T(V, x, y, len(V))
if answer:
return answer
return None
print(solve([(2,2),(1,4),(1,2)], 5))
It prints one possible solution:
[(2, 2), (1, 2)]
We have a directed graph G = (V, E) for a comm. network with each edge having a probability of not failing r(u, v) (defined as edge weight) which lies in interval [0, 1]. The probabilities are independent, so that from one vertex to another, if we multiply all probabilities, we get the the probability of the entire path not failing.
I need an efficient algorithm to find a most reliable path from one given vertex to another given vertex (i.e., a path from the first vertex to the second that is least likely to fail). I am given that log(r · s) = log r + log s will be helpful.
This is what I have so far -:
DIJKSTRA-VARIANT (G, s, t)
for v in V:
val[v] ← ∞
A ← ∅
Q ← V to initialize Q with vertices in V.
val[s] ← 0
while Q is not ∅ and t is not in A
do x ← EXTRACT-MIN (Q)
A ← A ∪ {x}
for each vertex y ∈ Adj[x]
do if val[x] + p(x, y) < val[y]:
val[y] = val[x] + p(x, y)
s is the source vertex and t is the destination vertex. Of course, I have not exploited the log property as I am not able to understand how to use it. The relaxation portion of the algorithm at the bottom needs to be modified, and the val array will capture the results. Without log, it would probably be storing the next highest probability. How should I modify the algorithm to use log?
Right now, your code has
do if val[x] + p(x, y) < val[y]:
val[y] = val[x] + p(x, y)
Since the edge weights in this case represent probabilities, you need to multiply them together (rather than adding):
do if val[x] * p(x, y) > val[y]:
val[y] = val[x] * p(x, y)
I've changed the sign to >, since you want the probability to be as large as possible.
Logs are helpful because (1) log(xy) = log(x) + log(y) (as you said) and sums are easier to compute than products, and (2) log(x) is a monotonic function of x, so log(x) and x have their maximum in the same place. Therefore, you can deal with the logarithm of the probability, instead of the probability itself:
do if log_val[x] + log(p(x, y)) > log_val[y]:
log_val[y] = log_val[x] + log(p(x, y))
Edited to add (since I don't have enough rep to leave a comment): you'll want to initialize your val array to 0, rather than Infinity, because you're calculating a maximum instead of a minimum. (Since you want the largest probability of not failing.) So, after log transforming, the initial log_val array values should be -Infinity.
In order to calculate probabilities you should multiply (instead of add) in the relaxation phase, which means changing:
do if val[x] + p(x, y) < val[y]:
val[y] = val[x] + p(x, y)
to:
do if val[x] * p(x, y) < val[y]:
val[y] = val[x] * p(x, y)
Using the Log is possible if the range is (0,1] since log(0) = -infinity and log(1) = 0, it means that for every x,y in (0,1]: probability x < probability y than: log(x) < log(y). Since we are maintaining the same relation (between probabilities) this modification will provide the correct answer.
I think you'll be able to take it from here.
I think I may have solved the question partially.
Here is my attempt. Edits and pointers are welcome -:
DIJKSTRA-VARIANT (G, s, t)
for v in V:
val[v] ← 0
A ← ∅
Q ← V to initialize Q with vertices in V.
val[s] ← 1
while Q is not ∅ and t is not in A
do x ← EXTRACT-MAX (Q)
A ← A ∪ {x}
for each vertex y ∈ Adj[x]
do if log(val[x]) + log(p(x, y)) > log(val[y]):
log(val[y]) = log(val[x]) + log(p(x, y))
Since I am to find the highest possible probability values, I believe I should be using >. The following questions remain -:
What should the initial values in the val array be?
Is there anything else I need to add?
EDIT: I have changed the initial val values to 0. However, log is undefined at 0. I am open to a better alternative. Also, I changed the priority queue's method to EXTRACT-MAX since it is the larger probabilities that need to be extracted. This would ideally be implemented on a binary max-heap.
FURTHER EDIT: I have marked tinybike's answer as accepted, since they have posted most of the necessary details that I require. The algorithm should be as I have posted here.
I have been trying to solve a problem on spoj.
Here is the link to the problem.
http://www.spoj.pl/problems/TAP2012B/
From what I have interpreted, I need to find the number of solutions of the equation xy+yz+xz = N
where n is given to us.
x>=y>=z
z can be zero.
But x and y cannot.
I tried doing solving this via implementing 3 for loops (bad approach).
It is giving the right answer but it is too slow.
Also, other people have solved it in almost no time (0.00)
So I am sure there is a very different approach to this problem.
For N = 20,
the number of different solutions is 5 :
(6,2,1)
(5,4,0)
(10,2,0)
(4,2,2,)
(20,1,0)
Maybe there is some brillian solution built on number-theory. But simply rethinking the task can reduce algorithm complexity as well.
For instance, we don't need a third loop as we can calculate z as (N - x*y)/(x+y). And we don't have to run y all the way to x every time, as we know, that z is not negative, therefore N >= xy.
N = 9747
for x in range(1, N+1):
max_y = min( N / x, x)
for y in range(1, max_y+1):
if (N - x*y) % (x+y) == 0:
z = (N - x*y) / (x+y)
if z <= y:
print x,y,z
You are approaching towards the right direction there will be 3 nested loops but try to reduce the no. of times the loop operates.... Follow the question and conditions carefully.....
You are obviously learning, so it would have had been better if you would do everything yourself, but you now have a great solution from akalenuk, and I hope that you will learn a few things from it as well.
If you are learning python at the same time, I will give you an equivalent solution to akalenuk's, but this time with list comprehension which is a very useful mechanism:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, min( N/x, x) + 1 )
for z in [ (N - x*y) / (x+y) ]
if (N - x*y) % (x+y) == 0
if z <= y]
The point is in pruning the solution space. The code above is already quite optimised. You might start with something like:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, x+1 )
for z in range(y+1)
if N == x*y + y*z + x*z]
This would run quite long. So, the first point of optimization may be adding the condition on y:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, x+1 )
if x*y <= N
for z in range(y+1)
if N == x*y + y*z + x*z]
This already cuts down the time considerably, as for non-promising y the z-loop is not run at all. Then, you notice that you may actually replace that if-statement by explicit computation of maximum y, as akalenuk did:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, min(x, N/x) +1)
for z in range(y+1)
if N == x*y + y*z + x*z]
This will again speed it up.
As you are learning, I recommend you try all these, and your own, time it, and learn from it.
I also recommend to try and time different, similar solutions