Is factorial of any number is Parallelizable? - parallel-processing

Can the calculation Factorial of any number is parallelizable? how ?

Sure, why not? Multiplication is associative. a * (b * (c * d)) == (((a * b) * c) * d) == (a * b) * (c * d). The implications for a divide-and-conquer parallelization scheme should be clear.
However, this would only have any tangible benefit for products of many numbers, and if you're talking about factorials, that means you're dealing with huge products, beyond the range of any computer's native integers, which means you're dealing with arbitrary-precision arithmetic... in which case you might have the opportunity to parallelize a single multiplication (Karatsuba multiplication is recursive, and the FFT in FFT-based multiplication is also very parallelizable), and if you can use up all of your resources that way, then there's no point in parallelizing at a higher layer.
For calculating reasonably-sized factorials, the fastest approach is probably the direct, single-threaded one, which has no overhead.

Related

How to find the n value

Consider two programs, A and B. Program A requires 1000 * n^2 (1000 multiplied by n to the power of 2) operations, and Program B requires 2^n (2 to the power of n) operations. For which values of n will Program A execute faster than Program B?
The easiest way to compare both of these complexities is just to map them out as graphs.
Just look where the lines intersect, that is 18.36. So if n is less than 18.36 then program a will execute faster.
For the exact answer, you can make the two equations equal each other then solve for n or just use WolframAlpha: https://www.wolframalpha.com/input/?i=1000x%5E2%3D2%5Ex
For n > 18.3
Solve 1000 * n^2 = 2^n for the exact solution or use WolframAlpha

Can one compute the nth Fibonacci number in time O(n) or O(1)? Why?

I asked myself if one can compute the nth Fibonacci number in time O(n) or O(1) and why?
Can someone explain please?
Yes. It is called Binet's Formula, or sometimes, incorrectly, De Moivre's Formula (the real De Moivre's formula is another, but De Moivre did discover Binet's formula before Binet), and involves the golden ratio Phi. The mathematical reasoning behind this (see link) is a bit involved, but doable:
While it is an approximate formula, Fibonacci numbers are integers -- so, once you achieve a high enough precision (depends on n), you can just approximate the number from Binet's formula to the closest integer.
Precision however depends on constants, so you basically have two versions, one with float numbers and one with double precision numbers, with the second also running in constant time, but slightly slower. For large n you will need an arbitrary precision number library, and those have processing times that do depend on the numbers involved; as observed by #MattTimmermans, you'll then probably end up with a O(log^2 n) algorithm. This should happen for large enough values of n that you'd be stuck with a large-number library no matter what (but I'd need to test this to be sure).
Otherwise, the Binet formula is mainly made up of two exponentiations and one division (the three sums and divisions by 2 are probably negligible), while the recursive formula mainly employs function calls and the iterative formula uses a loop. While the first formula is O(1), and the other two are O(n), the actual times are more like a, b n + c and d n + e, with values for a, b, c, d and e that depend on the hardware, compiler, implementation etc. . With a modern CPU it is very likely that a is not too larger than b or d, which means that the O(1) formula should be faster for almost every n. But most implementations of the iterative algorithm start with
if (n < 2) {
return n;
}
which is very likely to be faster for n = 0 and n = 1. I feel confident that Binet's formula is faster for any n beyond the single digits.
Instead of thinking about the recursive method, think of building the sequence from the bottom up, starting at 1+1.
You can also use a matrix m like this:
1 1
1 0
and calculate power n of it. then output m^n[0,0].

Distinct permutations of a string modulo a prime

I thought of the following problem recently, and I'm quite surprised that there doesn't seem to be anybody who asked this question yet:
Given a string, how many distinct permutations of it exist, modulo ?
I know the formula where is the length of the string, and are the count of each character (considering an alphabet of size ). So, the string toffee would have different permutations.
But this doesn't quite work anymore when can be really large (say ), since computing would go out of the range of long long int, and using BigIntegers would be too slow. Is there any way to compute this in, say, or time?
If I preprocessed the factorials from to , and my "strings" came in the form of an array of length where each element contained the count of each letter, would it be possible to compute it in or time?
Would appreciate any help on this :)
The trick is to note that p = 10^9 + 7 is a prime number. Therefore, we can use multiplicative inverses and Fermat's little theorem to turn the divisions in your formula into multiplications by the inverses:
n! / (a1!*...*ak!) =
n! * a1!^(p - 2) * ... * ak!^(p - 2) (mod p)
Which will be your formula mod p with no divisions and an easy implementation (just use modular exponentiation by squaring).
Complexity will be O(k log p + n), since we have O(k) multiplications, and for each one, an O(log p) exponentiation, and we must also compute n! and the factorial of each count.
This is easier to implement than cancelling out factors in the fraction.
The number of distinct permutations of a string is always an integer, despite being the result of a division. That's because the factors of the denominator essentially "knock out" some of the factors of the numerator. So you can eliminate the division as a post-factorial operation, instead dividing out the particular factors of the factorial which you've matched up with factors of the denominator.
Once you've got the division removed, you're just left with modular multiplication, which is simple.
Yes .. a solution exists. You can read about Modular multiplicative inverse algorithm. This
As the answer is with modulo 1000000007(which is a prime also), you can try Fermat's little theorem to solve this problem. If modulo number is mod Complexity is O(N + K * log(mod)).
If N isn't gigantic (that is, it's small enough to sift it using something like Sieve of Eratosthenes), you can calculate the prime factorisation of N! with a modified version of the sieve.
Then you can use the prime factorisation to calculate the division, cancelling out the factors present on both sides of the division.
Though this doesn't take into account the fact that you want the result modulo a prime number (where better solutions exist), it's probably useful to know in the general case.

finding ((a +b)/c)mod m

I would like to calculate:
((a+b)/c)mod m
I would like to know if there is any efficient way since a is too big but b , c and m fit in a simple 32-bit int.
There is no division operator in modular arithmetic. Instead, you must calculate the modular inverse of the denominator, then multiply. Thus, in your example, you would calculate a+b modulo m, calculate the modular inverse of c modulo m, then multiply the two modulo m. The modular inverse can be found using the extended Euclidean algorithm. If you don't know how to compute the modular inverse, ask.

Calculating complexity of algorithm

I am not sure if this is a valid question.
Let's assume there is an O(n^3) algorithm which sorts 100 numbers per day with a computing power x.
How many numbers will it be able to sort if the computing power is doubled ie., 2x .
I understand that i din't define 'computing power'. Please correct the question if it is ambiguous or wrong.
Big O notation does not give you eact time (real computer time). It is a method that try to understand effiency of algorithms independent of cpu or other specific computer features.
In mathamatics perpective, you can say that O(n^2) is more efficient than O(n^3). But in an engineer view point, for some values of n , O(n^3) can be better than O(n^2). This methods just says that for suffieciently large n, O(n^2) will be more efficient than O(n^3).
There is a good introduction to algorithm analsysis in you tube. First chapter is good for explaning those things:
MIT 6.046J / 18.410J Introduction to Algorithms
The Big O notation can only say that for the same machine, for sufficiently large n, O(n^2) is better than O(n^3). But for the same algorithm i think you can not make direct propotion betweeen computer power and output. If we double the computer power, the output doubled? Maybe yes but may be not. I think we can not say such a thing by just looking algorithm Big O.
N = 100 may be not big enough to be able to assume that the algorithm has already reached its asymptotic behaviour in terms of CPU usage, and so using the big O expression to extrapolate CPU usage for bigger datasets may generate erroneous results.
Though, you can try to determine if you are already on the asymptotic zone, measuring the CPU usage for datasets of other sizes (for instance, 50, 80, 120, etc.) and seeing how they fit on a t = C*N^3 curve, being C a constant to be determined.
If the fit is "good enough" after some given N, you can use the same curve to make predictions of CPU usage for bigger datasets.
In any case, you should consider those predictions as the lower limit of the CPU time required to compute some dataset because in practice, other computing resources as memory, caches or IO can become the bottleneck over the CPU usage.
Update: in response to Vapuru post and its comments:
For a typical O(N^3) algorithm the number of operations performed by a specific implementation is t = a + b * N + c * N^2 + d * N^3 (there may be other components, as log N, but as you will see, it doesn't actually matter). So, for two given data sets of size N1 and N2 you can calculate t1 and t2 respectively.
For the given OP problem, t2 / t1 = 2, so (a + b * N2 + c * N2^2 + d * N2^3) / (a + b * N1 + c * N1^2 + d * N1^3) = 2 and for N1 and N2 big enough that expression can be approximated as (d * N2^3)/(d * N1^3) = 2 that can be further simplified as (N2/N1)^3 = 2 and so N2 = N1 * 2^(1/3).
That means that for big datasets, doubling the processing time (or doubling the processing speed and keeping time unchanged), allows to increase the size of the dataset approximately by a factor of 2^(1/3), that's 1.26 or a 26%.
In practice, other factors besides CPU speed may affect performance, so actually it should be read as N2/N1 < 1.26.

Resources