It's known that to check whether a number 'n' is prime or not we just need to check whether it has a factor less than the square root of n.
My question is isn't it is sufficient to check for all primes less than the square root of n.
Every integer n greater than 1 either is prime itself or is the product of prime numbers (Fundamental theorem of arithmetic). Thus if n isn't a prime itself it must be divisible by at least two primes. At least one of these must be less than or equal to √n (otherwise their product would be greater than n), so it is sufficient to check for all the primes less than or equal to √n.
We can argue like this:
Let the number to check be n. Let there be a number k <= sqrt(n) which divides n. Now, we can write k as follows:
k = (p_1^a_1)(p_2^a_2)...(p_x^a_x)
where p_1, p_2, ..., p_x are prime number less than or equal to k and a_1, a_2, ..., a_x >= 1. Now, since k divides n, and since we know that p_1, p_2, ..., p_x divides k, by transitivity, we can deduce that p_1, p_2, ..., p_x divides n. Thus, to prove that n is non-prime, it is sufficient to check if any of the prime numbers <= sqrt(n) divides n or not.
Yes, what you are saying is absolutely correct.
You just need to check for all the primes less than equal to squareRoot(n), but the point is you don't know whether the number is prime or not. So, you traverse till squareRoot(n)
Yes it is only need to check the factor less sqrt(n). But this algorithm is a little bit slow. I have another better algorithm called Miller_Rabin_primality My previous project code
Source code
Here is the Wiki
Related
I am trying to implement an efficient algorithm, that can find the prime factorization for a given number n. I also have a list of all prime numbers up to at least n.
An example: If I have a number n = 50, the result should be: 2, 5, 5.
My ideas so far:
Check if n == 1, if true return 1
Check if n == 2, if true return 2
If both 1. and 2. are false:
Divide n by 2 as often as possible and add 2 to the vector of results
Try to find the (possibly by 2 divided) n in the list of prime numbers.
If n is in the list, add it to the results and return the results.
Find the largest prime number in the list, that is smaller than n.
Divide by the prime number found in step 6. If division without rest is possible, add the prime number to the results.
Check if n==1 and return the result if true
Repeat the steps 5-9.
Is that algorithm efficient or do you have any ideas for improvement?
Your proposed algorithm is inefficient. You should divide not by the largest remaining prime, but by the smallest. And if the smallest squared is larger than what is left, what is left is prime.
Your existing algorithm will need O(n/log(n)) divisions on average. My improvement makes it O(sqrt(n)/log(n)) instead. Which is still not a particularly efficient factorization algorithm. But is fine out to a few million.
I have a number (in base 10) represented as a string with up to 10^6 digits. I want to check if this number is a power of two. One thing I can think of is binary search on exponents and using FFT and fast exponentiation algorithm, but it is quite long and complex to code. Let n denote the length of the input (i.e., the number of decimal digits in the input). What's the most efficient algorithm for solving this problem, as a function of n?
There are either two or three powers of 2 for any given size of a decimal number, and it is easy to guess what they are, since the size of the decimal number is a good approximation of its base 10 logarithm, and you can compute the base 2 logarithm by just multiplying by an appropriate constant (log210). So a binary search would be inefficient and unnecessary.
Once you have a trial exponent, which will be on the order of three million, you can use the squaring exponentiation algorithm with about 22 bugnum decimal multiplications. (And up to 21 doublings, but those are relatively easy.)
Depending on how often you do this check, you might want to invest in fast bignum code. But if it is infrequent, simple multiplication should be ok.
If you don't expect the numbers to be powers of 2, you could first do a quick computation mod 109 to see if the last 9 digits match. That will eliminate all but a tiny percentage of random numbers. Or, for an even faster but slightly weaker filter, using 64-bit arithmetic check that the last 20 digits are divisible by 220 and not by 10.
Here is an easy probabilistic solution.
Say your number is n, and we want to find k: n = 2^k. Obviously, k = log2(n) = log10(n) * log2(10). We can estimate log10(n) ~ len(n) and find k' = len(n) * log2(10) with a small error (say, |k - k'| <= 5, I didn't check but this should be enough). Probably you'll need this part in any solutions that can come in mind, it was mentioned in other answers as well.
Now let's check that n = 2^k for some known k. Select a random prime number P with from 2 to k^2. If remainders are not equal that k is definitely not a match. But what if they are equal? I claim that false positive rate is bounded by 2 log(k)/k.
Why it is so? Because if n = 2^k (mod P) then P divides D = n-2^k. The number D has length about k (because n and 2^k has similar magnitude due to the first part) and thus cannot have more than k distinct prime divisors. There are around k^2 / log(k^2) primes less than k^2, so a probability that you've picked a prime divisor of D at random is less than k / (k^2 / log(k^2)) = 2 log(k) / k.
In practice, primes up to 10^9 (or even up to log(n)) should suffice, but you have to do a bit deeper analysis to prove the probability.
This solution does not require any long arithmetics at all, all calculations could be made in 64-bit integers.
P.S. In order to select a random prime from 1 to T you may use the following logic: select a random number from 1 to T and increment it by one until it is prime. In this case the distribution on primes is not uniform and the former analysis is not completely correct, but it can be adapted to such kind of random as well.
i am not sure if its easy to apply, but i would do it in the following way:
1) show the number in binary. now if the number is a power of two, it would look like:
1000000....
with only one 1 and the rest are 0. checking this number would be easy. now the question is how is the number stored. for example, it could have leading zeroes that will harden the search for the 1:
...000010000....
if there are only small number of leading zeroes, just search from left to right. if the number of zeroes is unknown, we will have to...
2) binary search for the 1:
2a) cut in the middle.
2b) if both or neither of them are 0 (hopefully you can check if a number is zero in reasonable time), stop and return false. (false = not power of 2)
else continue with the non-zero part.
stop if the non-zero part = 1 and return true.
estimation: if the number is n digits (decimal), then its 2^n digits binary.
binary search takes O(log t), and since t = 2^n, log t = n. therefore the algorithm should take O(n).
assumptions:
1) you can access the binary view of the number.
2) you can compare a number to zero in a reasonable time.
My algorithm and the ones found in a possible duplicate are O(n) and too slow for the requirement.
1 <= n <= 5*10^6
Euclid's formula tells us that every Pythagorean triple (a, b, c) is formed from integer k, n,m, with m>n
a=k*(m^2-n^2)
b=2*k*m*n
c=k*(m^2+n^2)
And C is hypotenuse of some right triangle with integral sides, if it could be represented as product of integer k and sum of two non-equal integer squares. We can find prime factors of C and check that at least one factor is Pythagorean prime of form 4*p+1. It requires O(Sqrt(C)) time
As, #MBo has already suggested, we just need to check if n has a prime factor of the form 4k+1. This can be done in O(sqrt(n)) time by computing prime factorization of n.
However, if you need to do this for all values in the mentioned range, you can compute all primes of form 4k+1 using sieve. Then mark all multiples of these primes (in the range [1..5*10**6]) as valid hypotenuse.
This algorithm will compute this boolean function for all inputs in roughly O(N log N log log N) (for sieve) + about the same as sieve for second part? Formal analysis will depend on distribution of primes of form 4k+1. I am not sure how such analysis is done.
Whereas, factorization will take O(N sqrt N) time.
I'm having trouble with a randomized problem. :)
A, a randomized algorithm, determines whether an input x is a prime number.
This algorithm works the following way:
1- If x is prime, then A outputs YES
2- If x is not prime, then A outputs NO with the probability 3/4.
At least how many times should we run A, if we want to have the algorithm A output NO with the probability at least 1- (1/k)?
Note: One NO answer implies that a given input x is not prime.
Any idea?
If a number x is not a prime, the probability to yield 'yes' in n repeats of the algorithm is (1/4)^n = 4^(-n) = 2^(-2n).
So, if you want to achieve 1-(1/k), you are actually looking for False Positive with probability of at most 1/k, and from the above we want:
2^(-2n) <= 1/k //log_2 on both sides:
-2n <= log(1/k) = log(1)-log(k) = 0 - log(k)
2n >= log(k)
n >= log(k)/2
So you want to chose the smallest integer n possible such that n >= log(k)/2, to guarantee True Negative with probability of 1-1/k.
(Note: All log() are with base 2).
Example:
If you want to be correct 99% of the time, you actually are looking for 1-1/k=0.99, so 1/k=1/100 and k=100.
Now, according to the above formula, note that log_2(100) ~= 6.64, and thus the smallest n such that n >= log_2(100)/2 is n==4.
Meaning, you need to repeat the algorithm 4 times to achieve 99%.
Let's check this is correct:
First check that the probability is indeed greater than 99%: 1-(1/4)^4 = 1-(1/256) ~= 0.996 >= 0.99, so the probability is fine.
Check that for a smaller integer (n==3), we would have got worse than 99% correct answer: 1-(1/4)^3 = 1-1/64 ~= 0.984 < 0.99 - so we would have failed for n==3.
Given an array of integers, find a set of at least one integer which sums to 0.
For example, given [-1, 8, 6, 7, 2, 1, -2, -5], the algorithm may output [-1, 6, 2, -2, -5] because this is a subset of the input array, which sums to 0.
The solution must run in polynomial time.
You'll have a hard time doing this in polynomial time, as the problem is known as the Subset sum problem, and is known to be NP-complete.
If you do find a polynomial solution, though, you'll have solved the "P = NP?" problem, which will make you quite rich.
The closest you get to a known polynomial solution is an approximation, such as the one listed on Wikipedia, which will try to get you an answer with a sum close to, but not necessarily equal to, 0.
This is a Subset sum problem, It's NP-Compelete but there is pseudo polynomial time algorithm for it. see wiki.
The problem can be solved in polynomial if the sum of items in set is polynomially related to number of items, from wiki:
The problem can be solved as follows
using dynamic programming. Suppose the
sequence is
x1, ..., xn
and we wish to determine if there is a
nonempty subset which sums to 0. Let N
be the sum of the negative values and
P the sum of the positive values.
Define the boolean-valued function
Q(i,s) to be the value (true or false)
of
"there is a nonempty subset of x1, ..., xi which sums to s".
Thus, the solution to the problem is
the value of Q(n,0).
Clearly, Q(i,s) = false if s < N or s
P so these values do not need to be stored or computed. Create an array to
hold the values Q(i,s) for 1 ≤ i ≤ n
and N ≤ s ≤ P.
The array can now be filled in using a
simple recursion. Initially, for N ≤ s
≤ P, set
Q(1,s) := (x1 = s).
Then, for i = 2, …, n, set
Q(i,s) := Q(i − 1,s) or (xi = s) or Q(i − 1,s − xi) for N ≤ s ≤ P.
For each assignment, the values of Q
on the right side are already known,
either because they were stored in the
table for the previous value of i or
because Q(i − 1,s − xi) = false if s −
xi < N or s − xi > P. Therefore, the
total number of arithmetic operations
is O(n(P − N)). For example, if all
the values are O(nk) for some k, then
the time required is O(nk+2).
This algorithm is easily modified to
return the subset with sum 0 if there
is one.
This solution does not count as
polynomial time in complexity theory
because P − N is not polynomial in the
size of the problem, which is the
number of bits used to represent it.
This algorithm is polynomial in the
values of N and P, which are
exponential in their numbers of bits.
A more general problem asks for a
subset summing to a specified value
(not necessarily 0). It can be solved
by a simple modification of the
algorithm above. For the case that
each xi is positive and bounded by the
same constant, Pisinger found a linear
time algorithm.[2]
It is well known Subset sum problem which NP-complete problem.
If you are interested in algorithms then most probably you are math enthusiast that I advise you look at
Subset Sum problem in mathworld
and here you can find the algorithm for it
Polynomial time approximation algorithm
initialize a list S to contain one element 0.
for each i from 1 to N do
let T be a list consisting of xi+y,
for all y in S
let U be the union of T and S
sort U
make S empty
let y be the smallest element of U
add y to S
for each element z of U in
increasing order do //trim the list by
eliminating numbers
close one to another
if y<(1-c/N)z, set y=z and add z to S
if S contains a number between (1-c)s and s, output yes, otherwise no