I am given a list of integers (up to 1000) which multiply to a given integer n .
I need to find the highest power among all the divisors of the integer n .
For instance : 4,7,8 multiply to 224 and the highest power will then be 5 since 224=2^2*7*2^3=2^5*7.
The problem is, the 1000 integers can be as large as 2^64, hence n is very large.
What is a great algorithm to solve this ?
Difficult. I'd start checking small primes first (in your example: 4, 7, 8. The product has a factor 2^5. You divide by the powers of two, leaving 1, 7, 1. Then you do the same for 3, 5, 7 etc. up to X).
Now you need to find a larger prime p > X that is a higher power than the highest you found. Spending lots of time to find prime factors that occur only once seems wasteful. You need primes that are factors of multiple numbers. Calculate the gcd of each pair of numbers and look at prime factors of these numbers. There are lots of details that need working out, that's why I started with "difficult".
Worst case you can't easily find any prime that occurs twice, so you need to check if each of the numbers contains the square of a prime as factor.
As an example: You checked for factors up to 1000, and you found that the highest power of a prime was 83^3. So now you need to find a larger prime that is a fourth power or show there is none. Calculate the pairwise gcd's (greatest common divisor). A large prime could be a divisor of multiple of these gcd's coming from four different numbers, or p could be factor of three gcd's, with p^2 a factor of one number etc.
To clarify the principle: Say you have two HUGE numbers x and y, and you want to know which is the highest power of a prime which divides xy. You could factor x and y and go from there. If they are both primes or products of two large primes, say x = p or pq, and y = r or rs, this takes a long time.
Now calculate the gcd of x and y. If the greatest common divisor is z > 1, then z is a factor of x and y, so z^2 is a factor of xy. If the greatest common divisor is 1, then x and y have no common factor. Since we don't need factors that are not square, we look for squares and higher factors. For that you only need to divide by factors up to x^(1/3) or y^(1/3).
Related
assume array of N (N<=100000) elements a1, a2, .... ,an, and you are given range in it L, R where 1<=L<=R<=N, you are required to get number of values in the given range which are divisible by at least one number from a set S which is given also, this set can be any subset of {1,2,....,10}. a fast way must be used because it may ask you for more than one range and more than one S (many queries Q, Q<=100000), so looping on the values each time will be very slow.
i thought of storing numbers of values divisible by each number in the big set {1,2,....,10} in 10 arrays of N elements each, and do cumulative sum to get the number of values divisible by any specific number in any range in O(1) time, for example if it requires to get number of values divisible by at least one of the following: 2,3,5, then i add the numbers of values divisible by each of them and then remove the intersections, but i didn't properly figure out how to calculate the intersections without 2^10 or 2^9 calculations each time which will be also very slow (and possibly hugely memory consuming) because it may be done 100000 times, any ideas ?
Your idea is correct. You can use inclusion-exclusion principle and prefix sums to find the answer. There is just one more observation you need to make.
If there's a pair of numbers a and b in the set such that a divides b, we can remove b without changing the answer to the query (indeed, if b | x, then a | x). Thus, we always get a set such that no element divides any other one.
The number of such mask is smaller than 2^10. In facts, it's 102. Here's the code that computes it:
def good(mask):
for i in filter(lambda b: mask & (1 << (b - 1)), range(1, 11)):
if (any(i % j == 0 for j in filter(lambda b: mask & (1 << (b - 1)), range(1, i)))):
return False
return True
print(list(filter(good, range(1, 2 ** 10)))))
Thus, we the preprocessing requires approximately 100N operations and numbers to store (it looks reasonably small).
Moreover, there are most 5 elements in any "good" mask (it can be checked using the code above). Thus, we can answer each query using around 2^5 operations.
I would like to know if there is any way (like a formula) to estimate how many prime numbers are there in an interval [0,N]. i.e. "How many prime numbers there are up to 120?"
I don't want to count and I dont want to know which numbers are these. I just need a estimation of how many are them.
Thank you.
f(x) = number of primes less than x
f(x) can be approximated by x/logx.
There are better but more complicated approximations, but a function for calculating this exactly is not known yet.
I'm stuck at solving Subset_sum_problem.
Given a set of integers(S), need to compute non-empty subsets whose sum is equal to a given target(T).
Example:
Given set, S{4, 8, 10, 16, 20, 22}
Target, T = 52.
Constraints:
The number of elements N of set S is limited to 8. Hence a NP time solution is acceptable as N has a small upperbound.
Time and space complexities are not really a concern.
Output:
Possible subsets with sum exactly equal to T=52 are:
{10, 20, 22}
{4, 10, 16, 22}
The solution given in Wiki and in some other pages tries to check whether there exists such a subset or not (YES/NO).
It doesn't really help to compute all possible subsets as outlined in the above example.
The dynamic programming approach at this link gives single such subset but I need all such subsets.
One obvious approach is to compute all 2^N combinations using brute force but that would be my last resort.
I'm looking for some programmatic example(preferably C++) or algorithm which computes such subsets with illutrations/examples?
When you construct the dynamic-programming table for the subset sum problem you intialize most of it like so (taken from the Wikipedia article referenced in the question):
Q(i,s) := Q(i − 1,s) or (xi == s) or Q(i − 1,s − xi)
This sets the table element to 0 or 1.
This simple formula doesn't let you distinguish between those several cases that can give you 1.
But you can instead set the table element to a value that'd let you distinguish those cases, something like this:
Q(i,s) := {Q(i − 1,s) != 0} * 1 + {xi == s} * 2 + {Q(i − 1,s − xi) != 0} *4
Then you can traverse the table from the last element. At every element the element value will tell you whether you have zero, one or two possible paths from it and their directions. All paths will give you all combinations of numbers summing up to T. And that's at most 2N.
if N <= 8 why don't just go with 2^n solution?? it's only 256 possibilities that will be very fast
Just brute force it. If N is limited to 8, your total number of subsets is 2^8, which is only 256. They give constraints for a reason.
You can express the set inclusion as a binary string where each element is either in the set or out of the set. Then you can just increment your binary string (which can simply be represented as an integer) and then determine which elements are in the set or not using the bitwise & operator. Once you've counted up to 2^N, you know you've gone through all possible subsets.
The best way to do it is using a dynamic programming approach.However, dynamic programming just answers whether a subset sum exits or not as you mentioned in your question.
By dynamic programming, you can output all the solutions by backtracking.However, the overall time complexity to generate all the valid combinations is still 2^n.
So, any better algorithm than 2^n is close to impossible.
UPD:
From #Knoothe Comment:
You can modify horowitz-sahni's algorithm to enumerate all possible subsets.If there are M such sets whose sum equals S, then overall time complexity is in O(N * 2^(N/2) + MN)
I have some numbers of form 10N + K, where N is about 1000, and K is really small (lower than 500). I want to test these numbers for primality. Currently I'm using Fermat's test by base 2, preceded by checking small factors (<10000).
However, this is rather slow for my purposes. Is there any algorithm quicker than that? Can this special form be exploited somehow?
Also, maybe if two numbers differ only in K, is it possible to test these two numbers a bit quicker?
If K has a factor of either 2 or 5 then 10^N + K is composite. This allows testing a small number quickly. Large primes are all such that P mod 6 = 1 or 5. You can use this to eliminate 2/3 of possible K values. With a little work you can set up a 2-4 wheel to avoid a lot of division:
increment <- either 2 or 4 as required
repeat
K <- K + increment
increment <- 6 - increment
if (K mod 5 = 0) then
continue
endif
until (isPrime(10^N + K) or (K > 500))
Trial factoring up to 10,000 if fine. Are you building a list of the primes up to 10,000 first? Use Eratosthenes' Sieve to create the list and just read off numbers.
Running a Fermat Test base 2 is a good start, it finds a lot of composites reasonably quickly.
After that you need to implement the probabilistic Miller-Rabin test, and run it enough times that it is more probable your hardware has failed rather than the number is composite.
Also, maybe if two numbers differ only in K, is it possible to test these two numbers a bit quicker?
To check the primes in a relatively small interval like [10N+K1, 10N+K2]
you can use the sieve of Erathostenes to check for divisibility by small numbers.
The remaining prime candidates can then be checked by a probabilistic test like Miller-Rabin.
To understand the problem,let us consider these examples first:
46 = (22)6 = 212 = (23)4 = 84 = 163 = 4096.
Thus,we can say that 46,212,84 and 163 are same.
273 = 39 = 19683
so, both 273 and 39 are identical.
Now the problem is, for any given pair of ab how to compute all others possible (if any)xy where, ab = xy.I am interested in an algorithm that can be efficiently implemented in C/C++.
For example:
If the inputs are like this:
4,6 desired output :(2,12),(8,4)
8,4 desired output :(2,12),(2,6)
27,3 desired output :(3,9)
12,6 desired output :(144,3),(1728,2)
7,5 desired output : No duplicate possible
This is mostly a math problem. You can extract all the prime factors of a number, and you'll get a list of prime numbers and their exponents, i.e., 216000 = 26 * 33 * 53. Then take the GCD of the exponents: GCD(6,3,3) = 3. Divide the exponents by the GCD to get the smallest root of the number, 22 * 31 * 51 = 60. Then factor the GCD — factors of 3 are 1 and 3. There is one way to express the number as an integral power for each factor of the GCD. You can express it as (603)1 or (601)3.
EDIT: fixed math error.
If integers is the only thing you're interested in, you could just start extracting integer roots from the target number, and checking if the result is an integer.
You even have a convenient stop condition - whenever the root is below 2 you can stop. That is, the algorithm:
Given a result
N <- 2
Compute Nth root.
If it's an integer: add to answers
If it's < 2, exit loop
N += 1, back to previous step
This algorithm will always terminate.
I believe that this problem is equivalent to the Integer factorization problem.
I said this because we can convert any composite number to a unique product of prime numbers
(see Fundamental theorem of arithmetic) and then start creating combinations with the factors and the powers.
Update: for example: 46
we convert it to a power of a prime factor, so we have 212.
Now we increase the base exponentially and we have: 46, 84 ... until the exponent becomes 1.
I finally solved it myself.Using a naive integer factorization algorithm my solution look like this.It can be optimized further by using Pollard's rho algorithm
EDIT: Code updated, now it can handle composite bases.Please point if it has certain other bugs too :)
The smallest base that makes sense is 2. Also, the smallest exponent that makes sense is 2.
Given the result, you can determine the largest possible exponent.
Example: 4096 = 2^12, biggest exponent is 12.
This also works with results that aren't powers of 2: 19683 is a bit bigger than 2^14, so you won't be seeing any exponents bigger than 14.
Now you can take your number and work your way down from the top exponent toward 2 (the smallest exponent). For every trial exponent exp, take the exp-th root of the result; if that comes out as a clean integer, then you've found one solution.
You can use logarithms to calculate the log2 of a result, and to take the n-th root of a number. But you will need to watch out for rounding errors.
The advantage of this approach is that once you've set things up, you can just run down a simple loop, and once done you have all your results.