Efficient polynomial evaluation with Horner's Algorithm - algorithm

I have the equation y = 3(x+1)^2 + 5(x+1)^4.
Using Horner's scheme I could evaluate this polynomial in this form, y = 8+x(26+x(33+x(20+5x))), thus requiring 8 arithmetic operations.
I could also evaluate it in this form, y = (x+1)^2 * ((5x+10)x+8), requiring 7 operations.
I've been told this can be done in 5 operations but Horner's algorithm is supposed to be most efficient and it can only do it in 7 operations. Am I missing something?

Let a = (x+1)^2, that's 2 ops. Then y=3a + 5a^2 = a(3+5a), 3 more ops for a total of 5.

3(x+1)^2 + 5(x+1)^4 = (x+1)^2[3 + 5(x+1)^2].
I can do that in 5 operations:
1) x+1
2) (x+1)^2
3) 5(x+1)^2
4) 5(x+1)^2 + 3
5) (x+1)^2[5(x+1)^2 + 3]

Related

Any useful mathematical function / algorithm to break down big numbers?

So what I want to do is breaking down numbers that are dozens of thousands big into smaller numbers, preferably 2~9.
The first thing came to my mind was prime factorization, for instance the number 49392 can be expressed as (2 x 2 x 2 x 2 x 3 x 3 x 7 x 7 x 7). But there are prime numbers and numbers such as 25378 = 2 × 12689 that cant be expressed with only multiplication.
So I want to break these numbers down using multiplication and addition, for example, the number 25378 could be expressed as 25346 + 32 = (2 × 19 × 23 × 29) + (2^5). Still, 23 and 29 are too big but I just picked random number just to show what I mean by using addtion and multiplication together to express big numbers, I'm sure there's a better combination of number that express 25378 than 25346 and 32.
Anyways, I thought programming this would involve ton of unnecessary if statement and would be incredibly slow in the big picture. So I was wondering, if there is a mathematical algorithm or function that does this thing? If not, I could just optimize the code myself, but I was just curious, I couldn't find anything on google myself though.
Assuming the problem is to write a number as the simplest expression containing the numbers 1-9, addition and multiplication (simplest = smallest number of operators), then this Python program does this in O(N^2) time.
A number N can be written as the sum or product of two smaller numbers, so if you've precalculated the simplest way of constructing the numbers 1..N-1, then you can find the simplest way of constructing N in O(N) time. Then it's just a matter of avoiding duplicate work -- for example without loss of generality in the expressions A+B and AB, A<=B, and nicely printing out the final expression.
def nice_exp(x, pri):
if isinstance(x, int):
return str(x)
else:
oppri = 1 if x[0] == '*' else 0
if oppri < pri:
bracks = '()'
else:
bracks = ['', '']
return '%s%s %s %s%s' % (bracks[0], nice_exp(x[1], oppri), x[0], nice_exp(x[2], oppri), bracks[1])
def solve(N):
infinity = 1e12
size = [infinity] * (N+1)
expr = [None] * (N+1)
for i in range(N+1):
if i < 10:
size[i] = 1
expr[i] = i
continue
for j in range(2, i):
if j * j > i: break
if i%j == 0 and size[j] + size[i//j] + 1 < size[i]:
size[i] = size[j] + size[i//j] + 1
expr[i] = ('*', expr[j], expr[i//j])
for j in range(1, i):
if j > i-j: break
if size[j] + size[i-j] + 1 < size[i]:
size[i] = size[j] + size[i-j] + 1
expr[i] = ('+', expr[j], expr[i-j])
return nice_exp(expr[N], 0)
print(solve(25378))
Output:
2 * (5 + 4 * 7 * (5 + 7 * 8 * 8))

Multiply polynomials using DFT algorithm [duplicate]

I am new to FFTs so I am slightly confused on some concepts. So far the FFT examples I've seen for equation multiplication involve equations with consecutive exponents (i.e. A(x) = 1 + 3x + 5x^2 +... and B(x) = 4 + 6x + 9x^2 + ... and C(x) = A(x)*B(x)). However, it is possible to use FFT on two equations that do not have equal exponents? For example, is it possible to use FFT to multiply:
A(x) = 1 + 3x^2 + 9x^8
and
B(x) = 5x + 6 x^3 + 10x^8
in O(nlogn) time?
If not, are there any cases where the runtime will be O(nlogn)? For example, if the number of terms in the product is O(n) instead of O(n^2)?
Even if the runtime is more than O(nlogn), how can we use FFT to minimize the runtime?
yes it is possible to use DFFT on non equal exponent polynomials...
the missing exponents are just multiplied by 0 which is also a number... just rewrite your polynomials:
A(x) = 1 + 3x^2 + 9x^8
B(x) = 5x + 6x^3 + 10x^8
to something like this:
A(x) = 1x^0 + 0x^1 + 3x^2 + 0x^3 + 0x^4+ 0x^5+ 0x^6+ 0x^7 + 9x^8
B(x) = 0x^0 + 5x^1 + 0x^2 + 6x^3 + 0x^4+ 0x^5+ 0x^6+ 0x^7 + 10x^8
so your vectors for DFFT are:
A = (1,0,3,0,0,0,0,0, 9)
B = (0,5,0,6,0,0,0,0,10)
add zero's so the vector is the correct result size (max A exponent +1 + max B exponent +1) and also round up to closest power of 2 for DFFT usage so original sizes are 9,9 -> 9+9 -> 18 -> round up -> 32
A = (1,0,3,0,0,0,0,0, 9,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0)
B = (0,5,0,6,0,0,0,0,10,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0)
// | original | correct result | nearest power of 2 |
and do the DFFT stuff you want ... I assume you want to do something like this:
A' = DFFT(A)
B' = DFFT(B)
C(i)' = A'(i) * B'(i) // i=0..n-1
C= IDFFT(C')
which is O(n*log(n)). Do not forget that if you use DFFT (not DFT) n = 32 and not 18 !!! because n must be power of 2 for fast algorithm of DFT also if you want performance improvements than look at the DFFT weight matrices for DFFT(A),DFFT(B) they are the same so no need to compute them twice ...

Solving linear equations represented as a string

I'm given a string 2*x + 5 - (3*x-2)=x + 5 and I need to solve for x. My thought process is that I'd convert it to an expression tree, something like,
=
/ \
- +
/\ /\
+ - x 5
/\ /\
* 5 * 2
/\ /\
2 x 3 x
But how do I actually reduce the tree from here? Any other ideas?
You have to reduce it using axioms from algebra
a * (b + c) -> (a * b) + (a * c)
This is done by checking the types of each node in the pass tree. Once the thing is fully expanded into terms, you can then check they are actually linear, etc.
The values in the tree will be either variables or numbers. It isn't very neat to represent these as classes inheriting from some AbstractTreeNode class however, because cplusplus doesn't have multiple dispatch. So it is better to do it the 'c' way.
enum NodeType {
Number,
Variable,
Addition //to represent the + and *
}
struct Node {
NodeType type;
//union {char*, int, Node*[2]} //psuedo code, but you need
//something kind of like this for the
//variable name ("x") and numerical value
//and the children
}
Now you can query they types of a node and its children using switch case.
As I said earlier - c++ idiomatic code would use virtual functions but lack the necessary multiple dispatch to solve this cleanly. (You would need to store the type anyway)
Then you group terms, etc and solve the equation.
You can have rules to normalise the tree, for example
constant + variable -> variable + constant
Would put x always on the left of a term. Then x * 2 + x * 4 could be simplified more easily
var * constant + var * constant -> (sum of constants) * var
In your example...
First, simplify the '=' by moving the terms (as per the rule above)
The right hand side will be -1 * (x + 5), becoming -1 * x + -1 * 5. The left hand side will be harder - consider replacing a - b with a + -1 * b.
Eventually,
2x + 5 + -3x + 2 + -x + -5 = 0
Then you can group terms ever which way you want. (By scanning along, etc)
(2 + -3 + -1) x + 5 + 2 + -5 = 0
Sum them up and when you have mx + c, solve it.
Assuming you have a first order equation, check all the leaves on each side. On each side, have two bins: one to add up all the leaves containing a multiple of X and one for all the leaves containing a multiples of a constant. Either add to a bin or multiply each bin as you step up the tree along each branch from the leaves. You will end up with something that is conceptually like
a*x + b = c*x + d
At that point, you can just solve
x = (d - b) / (a - c)
Assuming the equation can reduce to f(x) = 0, and f(x) = a * x + b.
You can transform all the leaves in expression tree to f(x), for example : 2 -> 0 * x + 2, 3 * x -> 3 * x + 0, then you can do arithmetic operations of f(x) in expression tree. finally solve the equation f(x) = 0.
If the function is much more complicated than polynomial, you can do a binary search on x, and using the expression tree to calculate the left and right side of equation.

Dynamic programming idiom for combinations

Consider the problem in which you have a value of N and you need to calculate how many ways you can sum up to N dollars using [1,2,5,10,20,50,100] Dollar bills.
Consider the classic DP solution:
C = [1,2,5,10,20,50,100]
def comb(p):
if p==0:
return 1
c = 0
for x in C:
if x <= p:
c += comb(p-x)
return c
It does not take into effect the order of the summed parts. For example, comb(4) will yield 5 results: [1,1,1,1],[2,1,1],[1,2,1],[1,1,2],[2,2] whereas there are actually 3 results ([2,1,1],[1,2,1],[1,1,2] are all the same).
What is the DP idiom for calculating this problem? (non-elegant solutions such as generating all possible solutions and removing duplicates are not welcome)
Not sure about any DP idioms, but you could try using Generating Functions.
What we need to find is the coefficient of x^N in
(1 + x + x^2 + ...)(1+x^5 + x^10 + ...)(1+x^10 + x^20 + ...)...(1+x^100 + x^200 + ...)
(number of times 1 appears*1 + number of times 5 appears * 5 + ... )
Which is same as the reciprocal of
(1-x)(1-x^5)(1-x^10)(1-x^20)(1-x^50)(1-x^100).
You can now factorize each in terms of products of roots of unity, split the reciprocal in terms of Partial Fractions (which is a one time step) and find the coefficient of x^N in each (which will be of the form Polynomial/(x-w)) and add them up.
You could do some DP in calculating the roots of unity.
You should not go from begining each time, but at max from were you came from at each depth.
That mean that you have to pass two parameters, start and remaining total.
C = [1,5,10,20,50,100]
def comb(p,start=0):
if p==0:
return 1
c = 0
for i,x in enumerate(C[start:]):
if x <= p:
c += comb(p-x,i+start)
return c
or equivalent (it might be more readable)
C = [1,5,10,20,50,100]
def comb(p,start=0):
if p==0:
return 1
c = 0
for i in range(start,len(C)):
x=C[i]
if x <= p:
c += comb(p-x,i)
return c
Terminology: What you are looking for is the "integer partitions"
into prescibed parts (you should replace "combinations" in the title).
Ignoring the "dynamic programming" part of the question, a routine
for your problem is given in the first section of chapter 16
("Integer partitions", p.339ff) of the fxtbook, online at
http://www.jjj.de/fxt/#fxtbook

Google Code Jam 2008: Round 1A Question 3

At Google Code Jam 2008 round 1A, there is problem:
Calculate last three digits before the
decimal point for the number
(3+sqrt(5))^n
n can be big number up to 1000000.
For example: if n = 2 then (3+sqrt(5))^2 = 27.4164079... answer is 027.
For n = 3: (3+sqrt(5))^3 = 3935.73982... answer is 935.
One of the solution is to create matrix M 2x2 : [[0, 1], [-4, 6]] than calculate matrix P = M^n, Where calculation preformed by modulo 1000.
and the result is (6*P[0,0] + 28*P[0,1] - 1) mod 1000.
Who can explain me this solution?
I'll present a method to solve this problem without even understanding the solution.
Assuming that you are familiar with the fibonacci numbers:
ghci> let fib = 0 : 1 : zipWith (+) fib (tail fib)
ghci> take 16 fib
[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610]
And are also familiar with its closed form expression:
ghci> let calcFib i = round (((1 + sqrt 5) / 2) ^ i / sqrt 5)
ghci> map calcFib [0..15]
[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610]
And you notice the similarity of ((1 + sqrt 5) / 2)n and (3 + sqrt 5)n.
From here one can guess that there is probably a series similar to fibonacci to calculate this.
But what series? So you calculate the first few items:
ghci> let calcThing i = floor ((3 + sqrt 5) ^ i)
ghci> map calcThing [0..5]
[1,5,27,143,751,3935]
Guessing that the formula is of the form:
thingn = a*thingn-1 + b*thingn-2
We have:
27 = a*5 + b*1
143 = a*27 + b*5
We solve the linear equations set and get:
thingn = 4*thingn-1 + 7*thingn-2 (a = 4, b = 7)
We check:
ghci> let thing = 1 : 5 : zipWith (+) (map (* 4) (tail thing)) (map (* 7) thing)
ghci> take 10 thing
[1,5,27,143,761,4045,21507,114343,607921,3232085]
ghci> map calcThing [0..9]
[1,5,27,143,751,3935,20607,107903,564991,2958335]
Then we find out that sadly this does not compute our function. But then we get cheered by the fact that it gets the right-most digit right. Not understanding why, but encouraged by this fact, we try to something similar. To find the parameters for a modified formula:
thingn = a*thingn-1 + b*thingn-2 + c
We then arrive at:
thingn = 6*thingn-1 - 4*thingn-2 + 1
We check it:
ghci> let thing =
1 : 5 : map (+1) (zipWith (+)
(map (*6) (tail thing))
(map (* negate 4) thing))
ghci> take 16 thing == map calcThing [0..15]
True
Just to give an answer to a very old question:
Thanks to yairchu i've got the idea to reread the prove of Binet's formula on the wikipedia page. It's there not really that clear, but we can work with it.
We see on the wikipedia page there is a closed form with 'computation by rounding': Fn = ⌊φ/√5⌋n.
If we could replace the φ/√5 with 3 + √5 (call the latter x). We could compute the floor of xn fairly easily, especially mod 1000, by finding the nth term in our freshly constructed sequence (this is the analogon of F (later we will call this analogon U)).
What sequence are we looking for? Well, we'll try following the prove for the Binet's formula. We need a quadratic equation with x as a root. Let's say x2 = 6 x-4 this one has roots x and y := 3 - √5. The handy part is now:
Define Un (for every a and b) such:
Un = a xn + b yn
by definition of x and y you can see that
Un = 6 Un-1 - 4 Un-2
Now we can choose a and b freely. We need Un to be integers so I propose choosing a=b=1. Now is U0 = 2, U1 = 6, U2 = 28...
We still need to get our 'computation by rounding'. You can see that yn < 1 for every n (because y ≅ 0.76 < 1) so Un = xn + yn = ⌈xn⌉.
If we can compute Un we can find ⌊xn⌋, just subtract 1.
We could compute Un by it's recursive formula but that would require O(n) computation time. We can do better!
For computing such a recursive formula we can use matrices:
⌈ 0 1⌉ ⌈ U(n-1) ⌉ ⌈ U(n) ⌉
⌊-4 6⌋ ⌊ U(n) ⌋ = ⌊U(n+1)⌋
Call this matrix M. Now does M*(U(1), U(2)) compute (U(2), U(3)).
Now we can compute P = Mn-1 (notice that I use one less than n, you can see that this is right if you test the small cases: n=0, n=1, n=2) P*(6,28) gives us now the nth and (n+1)th term of our sequence so:
(P*(6,28))0 - 1 = ⌊xn⌋
Now we can take everything mod 1000 (this is simplifying the calculations (a lot)) and we get the desired result in computation time O(log(n)) (or even better with the computational wonders of powers of matrices (over a cyclic finite field)). This explains the very weird looking solution, I guess.
I don't know how to explain that, but the auther of the problem have compose this analysis.

Resources