Remove all the multiples of a given set of numbers from given range - algorithm

I am stuck on a problem, where it says, given a number N and a set of numbers, S = {s1,s2,.....sn} where s1 < s2 < sn < N, remove all the multiples of {s1, s2,....sn} from range 1..N
Example:
Let N = 10
S = {2,4,5}
Output: {1, 7, 9}
Explanation: multiples of 2 within range: 2, 4, 6, 8
multiples of 4 within range: 4, 8
multiples of 5 within range: 5, 10
I would like to have an algorithmic approach, psuedocode rather than complete solution.
What I have tried:
(Considering the same example as above)
1. For the given N, find all the prime factors of that number.
Therefore, for 10, prime-factors are: 2,3,5,7
In the given set, S = {2,4,5}, the prime-factors missing from
{2,3,5,7} are {3,7}.
2. First, check prime-factors that are present: {2,5}
Hence, all the multiples of them will be removed
{2,4,5,6,8,10}
3. Check for non-prime numbers in S = {4}
4. Check, if any divisor of these numbers has already been
previously processed.
> In this case, 2 is already processed.
> Hence no need to process 4, as all the multiples of 4
would have been implicitly checked by the previous
divisor.
If not,
> Remove all the multiples from this range.
5. Repeat for all the remaining non primes in the set.
Please suggest your thoughts!

It is possible to solve it in O(N log(n)) time and O(N) extra memory using something similar to the Sieve of Eratosthenes.
isMultiple[1..N] = false
for each s in S:
t = s
while t <= N:
isMultiple[t] = true
t += s
for i in 1..N:
if not isMultiple[i]:
print i
This uses O(N) memory to store the isMultiple array.
The time complexity is O(N log(n)). Indeed, the inner while loop will be performed N / s1 times for the first element in S, then N / s2 for the second, and so on.
We need to estimate the magnitude of N / s1 + N / s2 + ... + N / sn.
N / s1 + N / s2 + ... + N / sn
= N * (1/s1 + 1/s2 + ... + 1/sn) <= N * (1/1 + 1/2 + ... + 1/n).
The last inequality is due to the fact that s1 < s2 < ...
< sn, thus the worst case is when they take values {1, 2, .. n}.
However, the harmonic series 1/1 + 1/2 + ... + 1/n is in O(log(n)), (e.g. see this), thus the time complexity of the above algorithm is O(N log(n)).

basic solution:
let set X be our output set.
for each number, n, between 1 and N:
for each number, s, in set S:
if s divides n:
stop searching S, and move onto the next number,n.
else if s is the last element in S:
add n to the set X.
you can obviously remove multiples in S before running this algorithm, but I don't think prime numbers are the way to go

Since S is sorted, we can guarantee O(N) complexity by skipping elements in S already marked (http://codepad.org/Joflhb7x):
N = 10
S = [2,4,5]
marked = set()
i = 0
curr = 1
while curr <= N:
while curr < S[i]:
print curr
curr = curr + 1
if not S[i] in marked:
mult = S[i]
while mult <= N:
marked.add(mult)
mult = mult + S[i]
i = i + 1
curr = curr + 1
if i == len(S):
while curr <= N:
if curr not in marked:
print curr
curr = curr + 1
print list(marked)

Related

Count number of subsequences of A such that every element of the subsequence is divisible by its index (starts from 1)

B is a subsequence of A if and only if we can turn A to B by removing zero or more element(s).
A = [1,2,3,4]
B = [1,4] is a subsequence of A.(Just remove 2 and 4).
B = [4,1] is not a subsequence of A.
Count all subsequences of A that satisfy this condition : A[i]%i = 0
Note that i starts from 1 not 0.
Example :
Input :
5
2 2 1 22 14
Output:
13
All of these 13 subsequences satisfy B[i]%i = 0 condition.
{2},{2,2},{2,22},{2,14},{2},{2,22},{2,14},{1},{1,22},{1,14},{22},{22,14},{14}
My attempt :
The only solution that I could came up with has O(n^2) complexity.
Assuming the maximum element in A is C, the following is an algorithm with time complexity O(n * sqrt(C)):
For every element x in A, find all divisors of x.
For every i from 1 to n, find every j such that A[j] is a multiple of i, using the result of step 1.
For every i from 1 to n and j such that A[j] is a multiple of i (using the result of step 2), find the number of B that has i elements and the last element is A[j] (dynamic programming).
def find_factors(x):
"""Returns all factors of x"""
for i in range(1, int(x ** 0.5) + 1):
if x % i == 0:
yield i
if i != x // i:
yield x // i
def solve(a):
"""Returns the answer for a"""
n = len(a)
# b[i] contains every j such that a[j] is a multiple of i+1.
b = [[] for i in range(n)]
for i, x in enumerate(a):
for factor in find_factors(x):
if factor <= n:
b[factor - 1].append(i)
# There are dp[i][j] sub arrays of A of length (i+1) ending at b[i][j]
dp = [[] for i in range(n)]
dp[0] = [1] * n
for i in range(1, n):
k = x = 0
for j in b[i]:
while k < len(b[i - 1]) and b[i - 1][k] < j:
x += dp[i - 1][k]
k += 1
dp[i].append(x)
return sum(sum(dpi) for dpi in dp)
For every divisor d of A[i], where d is greater than 1 and at most i+1, A[i] can be the dth element of the number of subsequences already counted for d-1.
JavaScript code:
function getDivisors(n, max){
let m = 1;
const left = [];
const right = [];
while (m*m <= n && m <= max){
if (n % m == 0){
left.push(m);
const l = n / m;
if (l != m && l <= max)
right.push(l);
}
m += 1;
}
return right.concat(left.reverse());
}
function f(A){
const dp = [1, ...new Array(A.length).fill(0)];
let result = 0;
for (let i=0; i<A.length; i++){
for (d of getDivisors(A[i], i+1)){
result += dp[d-1];
dp[d] += dp[d-1];
}
}
return result;
}
var A = [2, 2, 1, 22, 14];
console.log(JSON.stringify(A));
console.log(f(A));
I believe that for the general case we can't provably find an algorithm with complexity less than O(n^2).
First, an intuitive explanation:
Let's indicate the elements of the array by a1, a2, a3, ..., a_n.
If the element a1 appears in a subarray, it must be element no. 1.
If the element a2 appears in a subarray, it can be element no. 1 or 2.
If the element a3 appears in a subarray, it can be element no. 1, 2 or 3.
...
If the element a_n appears in a subarray, it can be element no. 1, 2, 3, ..., n.
So to take all the possibilities into account, we have to perform the following tests:
Check if a1 is divisible by 1 (trivial, of course)
Check if a2 is divisible by 1 or 2
Check if a3 is divisible by 1, 2 or 3
...
Check if a_n is divisible by 1, 2, 3, ..., n
All in all we have to perform 1+ 2 + 3 + ... + n = n(n - 1) / 2 tests, which gives a complexity of O(n^2).
Note that the above is somewhat inaccurate, because not all the tests are strictly necessary. For example, if a_i is divisible by 2 and 3 then it must be divisible by 6. Nevertheless, I think this gives a good intuition.
Now for a more formal argument:
Define an array like so:
a1 = 1
a2 = 1× 2
a3 = 1× 2 × 3
...
a_n = 1 × 2 × 3 × ... × n
By the definition, every subarray is valid.
Now let (m, p) be such that m <= n and p <= n and change a_mtoa_m / p`. We can now choose one of two paths:
If we restrict p to be prime, then each tuple (m, p) represents a mandatory test, because the corresponding change in the value of a_m changes the number of valid subarrays. But that requires prime factorization of each number between 1 and n. By the known methods, I don't think we can get here a complexity less than O(n^2).
If we omit the above restriction, then we clearly perform n(n - 1) / 2 tests, which gives a complexity of O(n^2).

How to make the run time of the program to ϴ n

The requirement is that the input will be set of integer ranging from -5 to 5, the result should give the longest subset of the integer, in which the total must be greater or equal to zero.
I can only come up with the following:
The input will be input[0 to n]
let start, longestStart, end, longestEnd, sum = 0
for i=0 to n-1
start = i
sum = input[i]
for j=1 to n
if sum + input[j] >= 0 then
end=j;
if end - start > longestEnd - longestStart then
longestStart = start;
longestEnd = end;
However this is ϴ(n^2). I would like to know what are the ways to make this loop become ϴ(n)
Thank you
Since
a - b == (a + n) - (b + n)
for any a, b or n, we can apply this to the array of numbers, keeping a running total of all elements from 0 to current. From the above equation, the sum of any subarray from index a to b is sum(elements 0-b) - sum(elements 0-a).
By keeping track of local minima and maxima, and the sums to them, you can find the subarray with the greatest range in one pass, ie O(n).

I have to find the nth number that contains the digit k or is divisible by k. (2 <= k <= 9)

Example – if n = 15 & k = 3 Answer : 33 (3, 6, 9, 12, 13, 15, 18, 21, 23, 24, 27, 30, 31, 32, 33)
I started following the sequence but couldn't formulate it
for multiples of 3 -> 3+3+3+4+3+3+4+3+3+4
for containing digit 3 ->
{
range in diff = 100 -> 1+1+1+10+1+1+1+1+1+1 = f(n) say;
range in diff = 1000 ->
f(n)+f(n)+f(n)+10*f(n)+f(n)+f(n)+f(n)+f(n)+f(n)+f(n) = ff(n) say
range in diff = 10000 ->
ff(n) + ff(n) + ff(n) + 10*ff(n)+ff(n) + ff(n) + ff(n)+ff(n) + ff(n) + ff(n)
same goes further.
}
I have to answer in better than O(n) or in O(1) if possible, Please don't suggest methods like to check every number in a for loop. Thanks.
Edit-I have searched everywhere but couldn't find it answered anywhere so , It's not a duplicate.
Here's one way to think about it that could point you along at least one direction (or, alternatively, a wild-goose chase). Separate the two questions and remove overlapping results:
(1) How many j-digit numbers are divisible by k ? [j 9's / k] - [(j-1) 9's / k]
(2) How many j-digit numbers include the digit k? 9 * 10^(k-1) - 8 x 9^(k-1)
Now we need to subtract the j-digit numbers that are both divisible by k and include the digit k. But how many are there?
Use divisibility rules to consider the different cases. For example:
k = 2
If k is the rightmost digit, any combination of the previous j-1 digits would work.
Otherwise, only combinations with 0,4,6 or 8 as the rightmost digit would work.
k = 5
If k is the rightmost digit, any combination of the previous j-1 digits would work.
Otherwise, only combinations with 0 or 5 as the rightmost digit would work.
etc.
(Addendum: I asked the combinatoric question on math.stackexchange and got some interesting answers. And here's a link to the OP's question on math.stackexchange: https://math.stackexchange.com/questions/1884303/the-n-th-number-that-contains-the-digit-k-or-is-divisible-by-k-2-le-k-l )
Following up on גלעד ברקן's answer, if you have an O(1) way of calculating d(j, k) = numbers with at least one digit k up to j, discarding numbers that are divisible by k, then you can calculate e(j, k) = numbers with at least on digit k or divisible by k under j as j/k + d(j, k).
This allows you to find f(n, k) with binary search, since k <= f(n, k) <= k*n and e(j, k) = n <=> f(n, k) = j: you essentially try to guess which j will yield the expected n, in O(log n) tries.
I agree with גלעד ברקן's observation regarding divisibility rules for calculating d(j, k) efficiently; but they are not trivial to implement, except for k=5 and k=2.
I strongly doubt that you can improve on O(log n) for this problem; and it may not even be reachable for some values of k.
This is more complex than I thought, but I think I figured out a solution for the simplest case (k = 2).
First I tried to simplify by asking the following question: Which position in the sequence have the numbers 10^i * k where i = 1, 2, 3, ...? For k = 2 the numbers are 20, 200, 2000, ...
i k n
1 2 20/2 = 10
2 2 200/2 + 2* 5 = 110
3 2 2000/2 + 2* 50 + 18* 5 = 1190
4 2 20000/2 + 2*500 + 18*50 + 162*5 = 12710
i 2 10^i + 2*10^(i-1)/2 + 18*10^(i-2)/2 + 162*10^(i-3)/2 + ?*10^(i-4)/2 + ...
In the last line I tried to express the pattern. The first part is the number dividable by 2. Then there are i-1 additional parts for the odd numbers with a 2 at first position, second and so on. The difficult part is to calculate the factors (2, 18, 162, ...).
Here a function returning the new factor for any i:
f(i) = 2 * 10^(i-2) - sum(10^(i-x-1)*f(x), x from 2 to i-1) = 2 * 9^(i-2) [thx #m69]
f(2) = 2
f(3) = 2*10 - (1*2) = 18
f(4) = 2*100 - (10*2 + 1*18) = 162
f(5) = 2*1000 - (100*2 + 10*18 + 1*162) = 1458
So using this information we can come up with the following algorithm:
Find the highest number 10^i*2 which does not exceed the position. (If n is in the range [positionOf(10^i*2), positionOf(10^i*2) + (10^i)] then we already know the solution: 10^i*2 + (n - positionOf(10^i*2)). E.g. if we find that i=2 we know that the next 100 values are all in the sequence: [201, 300], so if 110 <= n <= 210, then the solution is 200+(n-110) = n+90.)
int nn = positionOf(10^i * 2);
int s = 10^i * 2;
for (int ii = i; ii >= 0; ii--) {
for (int j = 1; j < 10; j++) {
if (j == 1 || j == 6) {
if (n <= nn + 10^ii)
return s + nn - n;
nn += 10^ii;
s += 10^ii;
int tmp = positionOf(10^ii);
if (nn + tmp > n)
break;
nn += tmp;
s += 10^ii;
} else {
int tmp = positionOf(10^ii * 2);
if (nn + tmp > n)
break;
nn += tmp;
s += 10^ii * 2;
}
}
}
return s;
This is only untested uncomplete pseudo-code (I know that you can't use ^ in Java), ii = 1 or 0 needs to be treated as special case, this missing and how to find i isn't shown either or the answer would become too long.
this can be solved using binary search+ digit dp.....
with time complexity of o(logn*)
for solution seecode:enter code herehttps://ideone.com/poxhzd

Count number of subsequences with given k modulo sum

Given an array a of n integers, count how many subsequences (non-consecutive as well) have sum % k = 0:
1 <= k < 100
1 <= n <= 10^6
1 <= a[i] <= 1000
An O(n^2) solution is easily possible, however a faster way O(n log n) or O(n) is needed.
This is the subset sum problem.
A simple solution is this:
s = 0
dp[x] = how many subsequences we can build with sum x
dp[0] = 1, 0 elsewhere
for i = 1 to n:
s += a[i]
for j = s down to a[i]:
dp[j] = dp[j] + dp[j - a[i]]
Then you can simply return the sum of all dp[x] such that x % k == 0. This has a high complexity though: about O(n*S), where S is the sum of all of your elements. The dp array must also have size S, which you probably can't even afford to declare for your constraints.
A better solution is to not iterate over sums larger than or equal to k in the first place. To do this, we will use 2 dp arrays:
dp1, dp2 = arrays of size k
dp1[0] = dp2[0] = 1, 0 elsewhere
for i = 1 to n:
mod_elem = a[i] % k
for j = 0 to k - 1:
dp2[j] = dp2[j] + dp1[(j - mod_elem + k) % k]
copy dp2 into dp1
return dp1[0]
Whose complexity is O(n*k), and is optimal for this problem.
There's an O(n + k^2 lg n)-time algorithm. Compute a histogram c(0), c(1), ..., c(k-1) of the input array mod k (i.e., there are c(r) elements that are r mod k). Then compute
k-1
product (1 + x^r)^c(r) mod (1 - x^k)
r=0
as follows, where the constant term of the reduced polynomial is the answer.
Rather than evaluate each factor with a fast exponentiation method and then multiply, we turn things inside out. If all c(r) are zero, then the answer is 1. Otherwise, recursively evaluate
k-1
P = product (1 + x^r)^(floor(c(r)/2)) mod (1 - x^k).
r=0
and then compute
k-1
Q = product (1 + x^r)^(c(r) - 2 floor(c(r)/2)) mod (1 - x^k),
r=0
in time O(k^2) for the latter computation by exploiting the sparsity of the factors. The result is P^2 Q mod (1 - x^k), computed in time O(k^2) via naive convolution.
Traverse a and count a[i] mod k; there ought to be k such counts.
Recurse and memoize over the distinct partitions of k, 2*k, 3*k...etc. with parts less than or equal to k, adding the products of the appropriate counts.
For example, if k were 10, some of the partitions would be 1+2+7 and 1+2+3+4; but while memoizing, we would only need to calculate once how many pairs mod k in the array produce (1 + 2).
For example, k = 5, a = {1,4,2,3,5,6}:
counts of a[i] mod k: {1,2,1,1,1}
products of distinct partitions of k:
5 => 1
4,1 => 2
3,2 => 1
products of distinct partitions of 2 * k with parts <= k:
5,4,1 => 2
5,3,2 => 1
4,1,3,2 => 2
products of distinct partitions of 3 * k with parts <= k:
5,4,1,3,2 => 2
answer = 11
{1,4} {4,6} {2,3} {5}
{1,4,2,3} {1,4,5} {4,6,2,3} {4,6,5} {2,3,5}
{1,4,2,3,5} {4,6,2,3,5}

Computational complexity of a algorithm

Algorithm 1. STACKSTUFF(n)
Input: Integer n
1) Let S = an empty Stack
2) Let X = -1
3) For i = 1 to 2n
4) S.Push(i)
5) End For
6) For i = 1 to n
7) Let X = S.Pop()
8) End For
Output: The contents of X
1) What is this algorithm written in pseudo code doing?
To my understanding, S.Push(i) adds item i on top of stack S. X = S.Pop() removes the item from the top of stack S and assigns it to X.
2) What is the computational complexity O(n) for algorithm 1, STACKSTUFF?
I believe the answer would be: O(3n)
The first loop would be 2n and the second for loop n, so 2n+n=3n.
Or... Would the answer just be O(n^2) since all we would have to do would be n*n?
3) If n > 0 then what is returned by the algorithm? What about n < 1
a) 2n
b) -1
c) n-1
d) n+1
e) None of the above
This last bit really confuses me. From my understanding, if n was always greater than 0, the algorithm would always return n+1, and if n was always less than 1, the algorithm would return n-1. However this is pure guess work...
If I thought about this logically, then let's say n was 3 for example. Since the first For loop is 1 to 2n, then this would mean that we would end up with the following stack S={1,2,3,4,5,6} as it added every number up to double n into S. The second For loop then pops 3 numbers so X ends up looking like this X={6,5,4}. If I am correct there... Should I assume that this was just a trick question and the answer is e, none of the above?
I just wanted to make sure my understanding here was correct before I continued studying. Thanks for any help.
1) The algoritm adds 1..2n to a stack, then pops n elements. Meaning that 1..n is left in the stack and the last popped element remains in X.
2) You are correct. The algoritm has complexity: 2 + (2n * 1) + (n * 1) = 3n + 2 = O(3n) = O(n).
3) The algoritm as storing the last popped element in X and then returning X and the last popped element is n + 1, so the answer should be d) n+1.
EDIT
Explanation on 3:
if n > 0:
X := -1
push 2n to the stack
stack = {1, 2, .. n, n + 1, ..., 2n}
pop n elements from the stack and store the popped element in X
first iteration:
X := stack.pop()
stack = {1, 2, .. n, n + 1, ..., 2n - 1}
X = 2n
... until we have popen n numbers.
stack = {1, 2, .. n}
X = n + 1
if n < 1
X := -1
because n < 1 we won't do any iterations in the loops
so X will not change and still be -1

Resources