Number of permutation of a particular string is divisible by a number - algorithm

Suppose I have a multiset of 10 digits, for example S = { 1, 1, 2, 2, 2, 3, 3, 3, 8, 9 }. Is there any method other than brute force to find the number of distinct permutations of the elements of S such that when a permutation is regarded as a ten digit integer, it is divisible by a particular number n ? n will be in the range 1 to 10000.
For example:
if S = { 1, 2, 3, 4, 6, 1, 2, 3, 4, 6 } and n = 10, the result is 0 (since no permutation of those 10 digits will ever give a number divisible by 10)
if S = { 1, 1, 3, 3, 5, 5, 7, 7, 9, 2} and n = 2, the result is 9! / 2^4 (since we must have the 2 at the end, there are 9! ways to permute the other elements, but there are four pairs of identical elements)

You could prune the search like so: find the prime factorization of NUM. Obviously to be divisible by NUM, a permutation needs to be divisible by all of NUM's prime factors. Hence you can use simple divisibility rules to avoid generating many invalid candidates.

I have some thoughts but it's not organized into an actual algorithm.
For N=2, we simply see how many even digits we can put on the end of our permutations and calculate the number that way.
For N=3, we know the sum of the digits has to be divisible by 3. This means we can freely put any 3s, 6s, 9s and 0s in our permutations, but any other digits we'll have to put in pairs that sum to 3, 6 or 9 (or a triplet of 1s). I don't think this would be too hard to implement.
For N=4, we can do something similar to N=2.
I think we can come up with cases like this for up to N=10 (N=7 might be tricky). Then, we might be able to do any N > 10 by factoring it. For example, if N=18, any and all permutations that are divisible by N are also divisible by 2 and 9. Of course if N is a prime number we might be in trouble.

My idea: sort the digits of S increasing and decreasing. Now you have the min and max that can be generated from S. Now take all multiples of N in the interval min, max and see which of them are formed by the digits in S.

Related

Dynamic Programming Problem for "disorder" in array

Given a sequence a=(a1,a2....an) from n postive integers. We call Disorder D(ak) of ak=(a1,a2...ak) the diference between ak's max from ak's min. We call Total Disorder the sum all D(ak) for all subsequences from k=2 to k=n. We are looking for a dp algorithm with a recursive solution for b*, witch is a permutation of a,and it achieves minimum D(ak) from k=2 to k=n.
Exmples:
a=(6, 2, 3, 1, 3, 3) then b*=(3, 3, 3, 2, 1, 6)[with D(b*) = 0 + 0 + 1 + 2 + 5 = 8]
a=(1, 3, 3, 3, 6, 6) then b*=(3, 3, 3, 6, 6, 1)[with D(b*) = 0 + 0 + 3 + 3 + 5 = 11]
The only thing i was able to prove was that at the end of b* the number will be either the max of a or min of a.
Pls help.
First sort the input array, and then consider building the result permutation backwards from the end towards the start.
For every element you will either remove the first or last element of the sorted array. Also, for every position k, the disorder of the subarray ending at that position is known -- it's just the difference between the two ends of the remaining element array.
To find the optimal selection, then, you can use DP[k,n] = the minimum disorder so far if we've chosen n elements from the front of the sorted array (with the remainder chosen from the back).
DP[k,n] is easily calculated from DP[k+1,n] and DP[k+1,n-1], and the minimum DP[0,?] is the minimum total disorder.

Count of Coprimes for each number

I recently came across this question in a hiring challenge :
Given an interval [L, R] (1 <= L,R <= 10^5), we need to tell number of coprimes of K in interval [L, R] for each K in [L, R].
e.g. L = 3, R = 7
for K = 3, number of coprimes in [3, 7] = 3 (4, 5, 7)
for K = 4, number of coprimes in [3, 7] = 3 (3, 5, 7)
for K = 5, number of coprimes in [3, 7] = 4 (3, 4, 6, 7)
...
By my approach, I am finding prime numbers upto R and then for each K, by its prime factors, counting number of coprimes, but I need better and efficient approach than this. Thanks in advance.
One approach would be the following.
For every number K perform the following steps:
find the prime factors of K (let us denote this set as D).
use inclusion-exclusion principle to count the numbers in the [L, R] interval which are multiples of at least one number in D. This number will represent the count of the numbers which are NOT co-prime with K.
you can see more details about this inclusion-exclusion approach in this answer (of mine).
that question involved arbitrary sets D (not necessarily comprising of prime numbers) -- in our case D contains prime numbers, thus the lowest common multiple (lcm) call from that answer can be computed more directly here as the product of the numbers in the current subset.
finally, to find the number of co-primes with K, subtract the previously found number from the total number of values in the [L, R] interval.
Remark: in step 2 we can similarly use the inclusion-exclusion principle to directly count the numbers which are co-prime with K (however, it feels more natural to me to count the multiples of numbers in set D). This would not require step 3 anymore.

Algorithm to find combination of n numbers with largest sum

Problem is simple -
Suppose I have an array of following numbers -
4,1,4,5,7,4,3,1,5
I have to find number of sets of k elements each that can be created from above numbers having largest sum. Two sets are considered to be different if they have at least one different element.
e.g.
if k = 2, then there can be two sets - {7,5} and {7,5}. Note: 5 appears twice in above array.
I think I can start with something like-
1. Sort array
2. Create two arrays. One for different number and an other in parallel for number's occurence.
But I am stuck now. Any suggestions?
The algorithm is as follows:
1) Sort elements in descending order.
2) Look at this array. It may look something like this:
a ... a b ... b c ... c d ...
| <- k -> |
Now obviously all elements a and b will be in the sets with the largest sum. You can't replace any of them with a smaller element, because then the sum wouldn't be the largest possible. So you have no choice here, you have to choose all a and b for any of the sets.
On the other hand only some of the elements c will be in those sets. So the answer is just the number of possibilities, to choose c's to fill the positions left in the sets, after you have taken all larger elements. That is the binomial coefficient:
count of c's choose (k - (count of elements larger than c))
For example for an array (already sorted here)
[9, 8, 7, 7, 5, 5, 5, 5, 4, 4, 2, 2, 1, 1, 1]
and k = 6, you must choose 9, 8 and both 7's for every set with the largest sum (which is 41). And then you can choose any two out of the four 5's. So the result will be 4 choose 2 = 6.
With the same array and k = 4, the result would be x choose 0 = 1 (that unique set is {9, 8, 7, 7}), with k = 7 the result would be 4 choose 3 = 4, and with k = 9: 2 choose 1 = 2 (choosing any 4 for the set with the largest sum).
EDIT: I edited the answer, because we figured it out that OP needs to count multisets.
First, find the largest k numbers in the array. This is of course easy, and if k is very small, you can do it in O(k) by performing k linear scans. If k is not so small, you can use a binary heap, or a priority queue or just sort the array to do that which is respectively O(n * log(k)) or O(n * log(n)) when using sorting.
Let assume that you have computed k largest numbers. Of course all sets of size k with the largest sum have to contain exactly these k largest numbers and no more other numbers. On the other hand, any different set doesn't have the largest sum.
Let count[i] be the number of occurrences of number i in the input sequence.
Let occ[i] be the number of occurrences of number i in the largest k numbers.
We can compute these both tables in very different ways, for example using a hash table or if input numbers are small, you can use an array indexed by these numbers.
Let B be the array of distinct numbers from the largest k numbers.
Let m be the size of B.
Now let's compute the answer. We will do it in m steps. After i-th step we will have computed the number of different multisets consisting of the first i numbers from B. At the beginning the result is 1 since there is only one empty multiset. In the i-th step, we will multiply the current result by the number of possible chooses of occ[B[i]] elements from count[B[i]] elements, which is equal to binomial(occ[i], count[i])
For example, let's consider your instance with added one more 7 at the end and k set to 3:
k = 3
A = [4, 1, 4, 5, 7, 4, 3, 1, 5, 7]
The largest three numbers in A are 7, 7, 5
At the beginning we have:
count[7] = 2
count[5] = 2
occ[7] = 2
occ[5] = 1
result = 1
B = [7, 5]
We start with the first element in B which is 7. Its count is 2 and its occ is also 2, so we do:
// binomial(2, 2) is 1
result = result * binomial(2, 2)
Next element in B is 5, its count is 2 and its occ is 1, so we do:
// binomial(2, 1) is 2
result = result * binomial(2, 1)
And the final result is 2, since there are two different multisets [7, 7, 5]
I'd create a sorted dictionary of the frequencies of occurrence of the numbers in the input. Then take the two largest numbers and multiply the number of times they occur.
In C++, it could look something like this:
std::vector<int> inputs { 4, 1, 4, 5, 7, 3, 1, 5};
std::map<int, int> counts;
for (auto i : inputs)
++counts[i];
auto last = counts.rbegin();
int largest_count = *last;
int second_count = *++last;
int set_count = largeest_count * second_count;
You can do the following:
1) Sort the elements in descending order;
2) define variable answer=1;
3) Start from the beginning of the array and for each new value you see, count the number of its occurrence (lets call this variable count). every time do: answer = answer * count. The pseudo-code should look like this.
find_count(Array A, K)
{
sort(A,'descending);
int answer=1;
int count=1;
for (int i=1,j=1; i<K && j<A.length;j++)
{
if(A[i] != A[i-1])
{
answer = answer *count;
i++;
count=1;
}
else
count++;
}
return answer;
}

Division free subset of maximum cardinality

A set S of positive integers is said to be “division free” if there do not exist distinct elements x and y of S such that x is divisible by y. For example, S = { 2, 3, 5 } is division free, but { 2, 3, 4, 5 } is not, since 4 is divisible by 2. How would you compute a maximum subset of { 1, 2, ..., n } that is division free? For example, when n = 10, then T = { 4, 6, 7, 9, 10 } is one of the maximum division free subsets.
My nephew in elementary school asked me this seemingly simple math problem. I can only think of brute force method. But it gets ugly when n is large. Is there a decent algorithm to solve it by computer?
Thanks.
Two numbers k and 2k couldn't belong to division-free subset simultaneously, so the subset can't consist of more than ceil(n/2) numbers.
Simply take all numbers from floor(n/2)+1 to n.
This is same as finding an independent set in a comparability graph, which has polynomial time algorithms, as it is a perfect graph.
Check out this: https://cs.stackexchange.com/questions/10274/how-to-find-the-maximum-independent-set-of-a-directed-graph

Given an array of integers, find the LARGEST number using the digits of the array such that it is divisible by 3

E.g.: Array: 4,3,0,1,5 {Assume all digits are >=0. Also each element in array correspond to a digit. i.e. each element on the array is between 0 and 9. }
In the above array, the largest number is: 5430 {using digits 5, 4, 3 and 0 from the array}
My Approach:
For divisibility by 3, we need the sum of digits to be divisible by 3.
So,
Step-1: Remove all the zeroes from the array.
Step-2: These zeroes will come at the end. {Since they dont affect the sum and we have to find the largest number}
Step-3: Find the subset of the elements of array (excluding zeroes) such that the number of digits is MAXIMUM and also that the sum of digits is MAXIMUM and the sum is divisible by 3.
STEP-4: The required digit consists of the digits in the above found set in decreasing order.
So, the main step is STEP-3 i.e. How to find the subset such that it contains MAXIMUM possible number of elements such that their sum is MAX and is divisible by 3 .
I was thinking, maybe Step-3 could be done by GREEDY CHOICE of taking all the elements and keep on removing the smallest element in the set till the sum is divisible by 3.
But i am not convinced that this GREEDY choice will work.
Please tell if my approach is correct.
If it is, then please suggest as to how to do Step-3 ?
Also, please suggest any other possible/efficient algorithm.
Observation: If you can get a number that is divisible by 3, you need to remove at most 2 numbers, to maintain optimal solution.
A simple O(n^2) solution will be to check all possibilities to remove 1 number, and if none is valid, check all pairs (There are O(n^2) of those).
EDIT:
O(n) solution: Create 3 buckets - bucket1, bucket2, bucket0. Each will denote the modulus 3 value of the numbers. Ignore bucket0 in the next algorithm.
Let the sum of the array be sum.
If sum % 3 ==0: we are done.
else if sum % 3 == 1:
if there is a number in bucket1 - chose the minimal
else: take 2 minimals from bucket 2
else if sum % 3 == 2
if there is a number in bucket2 - chose the minimal
else: take 2 minimals from bucket1
Note: You don't actually need the bucket, to achieve O(1) space - you need only the 2 minimal values from bucket1 and bucket2, since it is the only number we actually used from these buckets.
Example:
arr = { 3, 4, 0, 1, 5 }
bucket0 = {3,0} ; bucket1 = {4,1} bucket2 = { 5 }
sum = 13 ; sum %3 = 1
bucket1 is not empty - chose minimal from it (1), and remove it from the array.
result array = { 3, 4, 0, 5 }
proceed to STEP 4 "as planned"
Greedy choice definitely doesn't work: consider the set {5, 2, 1}. You'd remove the 1 first, but you should remove the 2.
I think you should work out the sum of the array modulo 3, which is either 0 (you're finished), or 1, or 2. Then you're looking to remove the minimal subset whose sum modulo 3 is 1 or 2.
I think that's fairly straightforward, so no real need for dynamic programming. Do it by removing one number with that modulus if possible, otherwise do it by removing two numbers with the other modulus. Once you know how many to remove, choose the smallest possible. You'll never need to remove three numbers.
You don't need to treat 0 specially, although if you're going to do that then you can further reduce the set under consideration in step 3 if you temporarily remove all 0, 3, 6, 9 from it.
Putting it all together, I would probably:
Sort the digits, descending.
Calculate the modulus. If 0, we're finished.
Try to remove a digit with that modulus, starting from the end. If successful, we're finished.
Remove two digits with negative-that-modulus, starting from the end. This always succeeds, so we're finished.
We might be left with an empty array (e.g. if the input is 1, 1), in which case the problem was impossible. Otherwise, the array contains the digits of our result.
Time complexity is O(n) provided that you do a counting sort in step 1. Which you certainly can since the values are digits.
What do you think about this:
first sort an array elements by value
sum up all numbers
- if sum's remainder after division by 3 is equal to 0, just return the sorted
array
- otherwise
- if sum of remainders after division by 3 of all the numbers is smaller
than the remainder of their sum, there is no solution
- otherwise
- if it's equal to 1, try to return the smallest number with remainder
equal to 1, or if no such, try two smallest with remainder equal to 2,
if no such two (I suppose it can happen), there's no solution
- if it's equal to 2, try to return the smallest number with remainder
equal to 2, or if no such, try two smallest with remainder equal to 1,
if no such two, there's no solution
first sort an array elements by remainder of division by 3 ascending
then each subset of equal remainder sort by value descending
First, this problem reduces to maximizing the number of elements selected such that their sum is divisible by 3.
Trivial: Select all numbers divisible by 3 (0,3,6,9).
Le a be the elements that leave 1 as remainder, b be the elements that leave 2 as remainder. If (|a|-|b|)%3 is 0, then select all elements from both a and b. If (|a|-|b|)%3 is 1, select all elements from b, and |a|-1 highest numbers from a. If the remainder is 2, then select all numbers from a, and |b|-1 highest numbers from b.
Once you have all the numbers, sort them in reverse order and concatenate. that is your answer.
Ultimately if n is the number of elements this algorithm returns a number that is al least n-1 digits long (except corner cases. see below).
NOTE: Take care of corner cases(i.e. what is |a|=0 or |b|=0 etc). (-1)%3 = 2 and (-2)%3 = 1 .
If m is the size of alphabet, and n is the number of elements, this my algorithm is O(m+n)
Sorting the data is unnecessary, since there are only ten different values.
Just count the number of zeroes, ones, twos etc. in O (n) if n digits are given.
Calculate the sum of all digits, check whether the remainder modulo 3 is 0, 1 or 2.
If the remainder is 1: Remove the first of the following which is possible (one of these is guaranteed to be possible): 1, 4, 7, 2+2, 2+5, 5+5, 2+8, 5+8, 8+8.
If the remainder is 2: Remove the first of the following which is possible (one of these is guaranteed to be possible): 2, 5, 8, 1+1, 1+4, 4+4, 1+7, 4+7, 7+7.
If there are no digits left then the problem cannot be solved. Otherwise, the solution is created by concatenating 9's, 8's, 7's, and so on as many as are remaining.
(Sorting n digits would take O (n log n). Unless of course you sort by counting how often each digit occurs and generating the sorted result according to these numbers).
Amit's answer has a tiny thing missing.
If bucket1 is not empty but it has a humongous value, lets say 79 and 97 and b2 is not empty as well and its 2 minimals are, say 2 and 5. Then in this case, when the modulus of the sum of all digits is 1, we should choose to remove 2 and 5 from bucket 2 instead of the minimal in bucket 1 to get the largest concatenated number.
Test case : 8 2 3 5 78 79
If we follow Amits and Steve's suggested method, largest number would be 878532 whereas the largest number possible divisble by 3 in this array is 879783
Solution would be to compare the appropriate bucket's smallest minimal with the concatenation of both the minimals of the other bucket and eliminate the smaller one.

Resources