DP solution to find if there is group of numbers which is divisible by M - algorithm

Let's say we have number N, such that 0 < N <= 10^6 and 2 <= M <= 10^3 and array of N elements a[1], a[2], ... a[N] (0<= a[i] <=10^9)\
Now we have to check if we can choose group of numbers from the array such that their sum will be divisible by M, and output "YES" or "NO".
Here are two examples:
N = 3, M =5 a={1,2,3} answer="YES"
N = 4, M = 6 a={3,1,1,3} answer="YES"
thanks in advance.

C++ solution.
//declare dp array of boolean values of size M
bool dp[M] = {0}; // init with fasle values
for(int i = 0; i < N; i++) {
bool ndp[M] = {0}; // init temporary boolean array
ndp[a[i] % M] = 1; // add a subset with one a[i] element
for(int j = 0; j < M; j++)
if(dp[j]) { // if we may find a subset of elements with sum = j (modulo M)
ndp[j] = 1; // copy existing values
ndp[(j + a[i]) % M] = 1; // extend the subset with a[i], which will give a sum = j + a[i] (modulo M)
}
// copy from ndp to dp before proceeding to the next element of a
for(int j = 0; j < M; j++) dp[j] = ndp[j];
}
//check dp[0] for the answer
The algorithm complexity will be O(N*M) which in your case is O(109)
Edit: Added ndp[a[i] % M] = 1; line in order to make dp[j] ever become nonzero.
There might be another alternative O(M * M * log(M) + N) solution which in your case is O(107) (but with big constant).
Notice that if substitute each a[i] with a[i] % M the problem statement does not change. Lets count the number of a[i] elements that give specific remainder j after division on M. If for some remainder j we found k elements in a then we can generate the following sums of subsets (that may produce unique remainder)
j, 2 * j % M, 3 * j % M ... k * j % M
Example: let M = 6 and for remainder 2 we found 5 elements in a. Then we have the following unique sums of subsets:
2 % 6, 2 * 2 % 6, 3 * 2 % 6, 4 * 2 % 6, 5 * 2 % 6
which is 0, 2, 4
store this information in boolean form {1, 0, 1, 0, 1, 0}
At most we have M such groups that produce M-size bool array of possible remainders.
Next we need to find all possible subsets that may appear if we will take elements of different groups. Lets say we merge two bool remainder arrays a and b if we can introduce new array c that will contain all possible remainder sums of elements from subset of a and b. Naive approach will require us to make two nested loops over a and b giving O(M2) merge time complexity.
We may reduce complexity to O(M * log(M)) using Fast Fourier Transform algo. Each bool array has a polynomial Σ ai*xi where coefficients ai are taken from bool array. If we want to merge two array we may just multiply their polynomials.
Overall complxity is O(M2 * log(M)) as we need to make M such merges.

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).

Length of Longest Subarray with all same elements

I have this problem:
You are given an array of integers A and an integer k.
You can decrement elements of A up to k times, with the goal of producing a consecutive subarray whose elements are all equal. Return the length of the longest possible consecutive subarray that you can produce in this way.
For example, if A is [1,7,3,4,6,5] and k is 6, then you can produce [1,7,3,4-1,6-1-1-1,5-1-1] = [1,7,3,3,3,3], so you will return 4.
What is the optimal solution?
The subarray must be made equal to its lowest member since the only allowed operation is reduction (and reducing the lowest member would add unnecessary cost). Given:
a1, a2, a3...an
the cost to reduce is:
sum(a1..an) - n * min(a1..an)
For example,
3, 4, 6, 5
sum = 18
min = 3
cost = 18 - 4 * 3 = 6
One way to reduce the complexity from O(n^2) to a log factor is: for each element as the rightmost (or leftmost) element of the candidate best subarray, binary search the longest length within cost. To do that, we only need the sum, which we can get from a prefix sum in O(1), the length (which we are searching on already), and minimum range query, which is well-studied.
In response to comments below this post, here is a demonstration that the sequence of costs as we extend a subarray from each element as rightmost increases monotonically and can therefore be queried with binary search.
JavaScript code:
function cost(A, i, j){
const n = j - i + 1;
let sum = 0;
let min = Infinity;
for (let k=i; k<=j; k++){
sum += A[k];
min = Math.min(min, A[k]);
}
return sum - n * min;
}
function f(A){
for (let j=0; j<A.length; j++){
const rightmost = A[j];
const sequence = [];
for (let i=j; i>=0; i--)
sequence.push(cost(A, i, j));
console.log(rightmost + ': ' + sequence);
}
}
var A = [1,7,3,1,4,6,5,100,1,4,6,5,3];
f(A);
def cost(a, i, j):
n = j - i
s = 0
m = a[i]
for k in range(i,j):
s += a[k]
m = min(m, a[k])
return s - n * m;
def solve(n,k,a):
m=1
for i in range(n):
for j in range(i,n+1):
if cost(a,i,j)<=k:
x = j - i
if x>m:
m=x
return m
This is my python3 solution as per your specifications.

Sum of products of elements of all subarrays of length k

An array of length n is given. Find the sum of products of elements of the sub-array.
Explanation
Array A = [2, 3, 4] of length 3.
Sub-array of length 2 = [2,3], [3,4], [2,4]
Product of elements in [2, 3] = 6
Product of elements in [3, 4] = 12
Product of elements in [2, 4] = 8
Sum for subarray of length 2 = 6+12+8 = 26
Similarly, for length 3, Sum = 24
As, products can be larger for higher lengths of sub-arrays calculate in modulo 1000000007.
What is an efficient way for finding these sums for subarrays of all possible lengths, i.e., 1, 2, 3, ......, n where n is the length of the array.
There is rather simple way:
Construct product of terms (1 + A[i] * x):
P = (1 + A[0] * x) * (1 + A[1] * x) * (1 + A[2] * x)...*(1 + A[n-1] * x)
If we open the brackets, then we'll get polynomial
P = 1 + B[1] * x + B[2] * x^2 + ... + B[n] * x^n
Kth coefficient, B[k], is equal to the sum of products of sets with length K - for example, B[n] = A[0]*A[1]*A[2]*..A[n-1], B[2] = A[0]*A[1] + A[0]*A[2] + ... + A[n-2]*A[n-1] and so on.
So to find sum of products of all possible sets, we have to find value of polynomial P for x = 1, then subtract 1 to remove leading 0th term. If we don't want to take into consideration single-element sets, then subtract B1 = sum of A[i].
Example:
(1+2)(1+3)(1+4) = 60
60 - 1 = 59
59 - (2 + 3 + 4) = 50 = 24 + 26 - as your example shows
We first create a recursive relation. Let f(n, k) be the sum of all products of sub-arrays of length k from an array a of length n. The base cases are simple:
f(0, k) = 0 for all k
f(n, 0) = 1 for all n
The second rule might seem a little counter-intuitive, but 1 is the zero-element of multiplication.
Now we find a recursive relation for f(n+1, k). We want the product of all subarrays of size k. There are two types of subarrays here: the ones including a[n+1] and the ones not including a[n+1]. The sum of the ones not including a[n+1] is exactly f(n, k). The ones including a[n+1] are exactly all subarrays of length k-1 with a[n+1] added, so their summed product is a[n+1] * f(n, k-1).
This completes our recurrence relation:
f(n, k) = 0 if n = 0
= 1 if k = 0
= f(n-1, k) + a[n] * f(n-1, k-1) otherwise
You can use a neat trick to use very limited memory for your dynamic programming, because function f only depends on two earlier values:
int[] compute(int[] a) {
int N = a.length;
int[] f = int[N];
f[0] = 1;
for (int n = 1; n < N; n++) {
for (int k = n; k >= 1; k--) {
f[k] = (f[k] + a[n] * f[k-1]) % 1000000007;
}
}
return f;
}

number of subarrays where sum of numbers is divisible by K

Given an array, find how many such subsequences (does not require to be contiguous) exist where sum of elements in that subarray is divisible by K.
I know an approach with complexity 2^n as given below. it is like finding all nCi where i=[0,n] and validating if sum is divisible by K.
Please provide Pseudo Code something like linear/quadratic or n^3.
static int numways = 0;
void findNumOfSubArrays(int [] arr,int index, int sum, int K) {
if(index==arr.length) {
if(sum%k==0) numways++;
}
else {
findNumOfSubArrays(arr, index+1, sum, K);
findNumOfSubArrays(arr, index+1, sum+arr[index], K);
}
}
Input - array A in length n, and natural number k.
The algorithm:
Construct array B: for each 1 <= i <= n: B[i] = (A[i] modulo K).
Now we can use dynamic programming:
We define D[i,j] = maximum number of sub-arrays of - B[i..n] that the sum of its elements modulo k equals to j.
1 <= i <= n.
0 <= j <= k-1.
D[n,0] = if (b[n] == 0), 2. Otherwise, 1.
if j > 0 :
D[n,j] = if (B[n] modulo k) == j, than 1. Otherwise, 0.
for i < n and 0 <= j <= k-1:
D[i,j] = max{D[i+1,j], 1 + D[i+1, D[i+1,(j-B[i]+k) modulo k)]}.
Construct D.
Return D[1,0].
Overall running time: O(n*k)
Acutally, I don't think this problem can likely be solved in O(n^3) or even polynomial time, if the range of K and the range of numbers in array is unknown. Here is what I think:
Consider the following case: the N numbers in arr is something like
[1,2,4,8,16,32,...,2^(N-1)]
,
in this way, the sums of 2^N "subarrays" (that does not require to be contiguous) of arr, is exactly all the integer numbers in [0,2^N)
and asking how many of them is divisible by K, is equivalent to asking how many of integers are divisible by K in [0, 2^N).
I know the answer can be calculated directly like (2^N-1)/K (or something) in the above case. But , if we just change a few ( maybe 3? 4? ) numbers in arr randomly, to "dig some random holes" in the perfect-contiguous-integer-range [0,2^N), that makes it looks impossible to calculate the answer without going through almost every number in [0,2^N).
ok just some stupid thoughts ... could be totally wrong.
Use an auxiliary array A
1) While taking input, store the current grand total in the corresponding index (this executes in O(n)):
int sum = 0;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
sum += arr[i];
A[i] = sum;
}
2) now,
for (int i = 0; i < n; i++)
for (int j = i; j < n; j++)
check that (A[j] - A[i] + arr[i]) is divisible by k
There you go: O(n^2)...

Minimum number of swaps needed to change Array 1 to Array 2?

For example, input is
Array 1 = [2, 3, 4, 5]
Array 2 = [3, 2, 5, 4]
Minimum number of swaps needed are 2.
The swaps need not be with adjacent cells, any two elements can be swapped.
https://www.spoj.com/problems/YODANESS/
As #IVlad noted in the comment to your question Yodaness problem asks you to count number of inversions and not minimal number of swaps.
For example:
L1 = [2,3,4,5]
L2 = [2,5,4,3]
The minimal number of swaps is one (swap 5 and 3 in L2 to get L1), but number of inversions is three: (5 4), (5 3), and (4 3) pairs are in the wrong order.
The simplest way to count number of inversions follows from the definition:
A pair of elements (pi,pj) is called an inversion in a permutation p if i < j and pi > pj.
In Python:
def count_inversions_brute_force(permutation):
"""Count number of inversions in the permutation in O(N**2)."""
return sum(pi > permutation[j]
for i, pi in enumerate(permutation)
for j in xrange(i+1, len(permutation)))
You could count inversion in O(N*log(N)) using divide & conquer strategy (similar to how a merge sort algorithm works). Here's pseudo-code from Counting Inversions translated to Python code:
def merge_and_count(a, b):
assert a == sorted(a) and b == sorted(b)
c = []
count = 0
i, j = 0, 0
while i < len(a) and j < len(b):
c.append(min(b[j], a[i]))
if b[j] < a[i]:
count += len(a) - i # number of elements remaining in `a`
j+=1
else:
i+=1
# now we reached the end of one the lists
c += a[i:] + b[j:] # append the remainder of the list to C
return count, c
def sort_and_count(L):
if len(L) == 1: return 0, L
n = len(L) // 2
a, b = L[:n], L[n:]
ra, a = sort_and_count(a)
rb, b = sort_and_count(b)
r, L = merge_and_count(a, b)
return ra+rb+r, L
Example:
>>> sort_and_count([5, 4, 2, 3])
(5, [2, 3, 4, 5])
Here's solution in Python for the example from the problem:
yoda_words = "in the force strong you are".split()
normal_words = "you are strong in the force".split()
perm = get_permutation(normal_words, yoda_words)
print "number of inversions:", sort_and_count(perm)[0]
print "number of swaps:", number_of_swaps(perm)
Output:
number of inversions: 11
number of swaps: 5
Definitions of get_permutation() and number_of_swaps() are:
def get_permutation(L1, L2):
"""Find permutation that converts L1 into L2.
See http://en.wikipedia.org/wiki/Cycle_representation#Notation
"""
if sorted(L1) != sorted(L2):
raise ValueError("L2 must be permutation of L1 (%s, %s)" % (L1,L2))
permutation = map(dict((v, i) for i, v in enumerate(L1)).get, L2)
assert [L1[p] for p in permutation] == L2
return permutation
def number_of_swaps(permutation):
"""Find number of swaps required to convert the permutation into
identity one.
"""
# decompose the permutation into disjoint cycles
nswaps = 0
seen = set()
for i in xrange(len(permutation)):
if i not in seen:
j = i # begin new cycle that starts with `i`
while permutation[j] != i: # (i σ(i) σ(σ(i)) ...)
j = permutation[j]
seen.add(j)
nswaps += 1
return nswaps
As implied by Sebastian's solution, the algorithm you are looking for can be based on inspecting the permutation's cycles.
We should consider array #2 to be a permutation transformation on array #1. In your example, the permutation can be represented as P = [2,1,4,3].
Every permutation can be expressed as a set of disjoint cycles, representing cyclic position changes of the items. The permutation P for example has 2 cycles: (2,1) and (4,3). Therefore two swaps are enough. In the general case, you should simply subtract the number of cycles from the permutation length, and you get the minimum number of required swaps. This follows from the observation that in order to "fix" a cycle of N elements, N-1 swaps are enough.
This problem has a clean, greedy, trivial solution:
Find any swap operation which gets both swapped elements in Array1 closer to their destination in Array2. Perform the swap operation on Array1 if one exists.
Repeat step1 until no more such swap operations exist.
Find any swap operation which gets one swapped element in Array1 closer to its destination in Array2. If such an operation exist, perform it on Array1.
Go back to step1 until Array1 == Array2.
The correctness of the algorithm can be proved by defining a potential for the problem as the sum of distances of all elements in array1 from their destination in array2.
This can be easily converted to another type of problem, which can be solved more efficiently. All that is needed is to convert the arrays into permutations, i.e. change the values to their ids. So your arrays:
L1 = [2,3,4,5]
L2 = [2,5,4,3]
would become
P1 = [0,1,2,3]
P2 = [0,3,2,1]
with the assignment 2->0, 3->1, 4->2, 5->3. This can only be done if there are no repeated items though. If there are, then this becomes harder to solve.
Converting permutation from one to another can be converted to a similar problem (Number of swaps in a permutation) by inverting the target permutation in O(n), composing the permutations in O(n) and then finding the number of swaps from there to an identity permutation in O(m).
Given:
int P1[] = {0, 1, 2, 3}; // 2345
int P2[] = {0, 3, 2, 1}; // 2543
// we can follow a simple algebraic modification
// (see http://en.wikipedia.org/wiki/Permutation#Product_and_inverse):
// P1 * P = P2 | premultiply P1^-1 *
// P1^-1 * P1 * P = P1^-1 * P2
// I * P = P1^-1 * P2
// P = P1^-1 * P2
// where P is a permutation that makes P1 into P2.
// also, the number of steps from P to identity equals
// the number of steps from P1 to P2.
int P1_inv[4];
for(int i = 0; i < 4; ++ i)
P1_inv[P1[i]] = i;
// invert the first permutation in O(n)
int P[4];
for(int i = 0; i < 4; ++ i)
P[i] = P2[P1_inv[i]];
// chain the permutations in O(n)
int num_steps = NumSteps(P, 4); // will return 2
// now we just need to count the steps in O(num_steps)
To count the steps, a simple algorithm can be devised, such as:
int NumSteps(int *P, int n)
{
int count = 0;
for(int i = 0; i < n; ++ i) {
for(; P[i] != i; ++ count) // could be permuted multiple times
swap(P[P[i]], P[i]); // look where the number at hand should be
}
// count number of permutations
return count;
}
This always swaps an item for a place where it should be in the identity permutation, therefore at every step it undoes and counts one swap. Now, provided that the number of swaps it returns is indeed minimum, the runtime of the algorithm is bounded by it and is guaranteed to finish (instead of getting stuck in an infinite loop). It will run in O(m) swaps or O(m + n) loop iterations where m is number of swaps (the count returned) and n is number of items in the sequence (4). Note that m < n is always true. Therefore, this should be superior to O(n log n) solutions, as the upper bound is O(n - 1) of swaps or O(n + n - 1) of loop iterations here, which is both practically O(n) (constant factor of 2 omitted in the latter case).
The algorithm will only work for valid permutations, it will loop infinitely for sequences with duplicate values and will do out-of-bounds array access (and crash) for sequences with values other than [0, n). A complete test case can be found here (builds with Visual Studio 2008, the algorithm itself should be fairly portable). It generates all possible permutations of lengths 1 to 32 and checks against solutions, generated with breadth first search (BFS), seems to work for all of permutations of lengths 1 to 12, then it becomes fairly slow but I assume it will just continue working.
Algorithm:
Check if the elements of list in the same position are equal. If yes, no swap is required. If no, swap the position of list-element wherever the element is matching
Iterate the process for the entire list elements.
Code:
def nswaps(l1, l2):
cnt = 0
for i in range(len(l1)):
if l1[i] != l2[i]:
ind = l2.index(l1[i])
l2[i], l2[ind] = l2[ind], l2[i]
cnt += 1
pass
return cnt
Since we already know that arr2 has the correct indexes of each element present in arr1. Therefore, we can simply compare the arr1 elements with arr2, and swap them with the correct indexes in case they are at wrong index.
def minimum_swaps(arr1, arr2):
swaps = 0
for i in range(len(arr1)):
if arr1[i] != arr2[i]:
swaps += 1
element = arr1[i]
index = arr1.index(arr2[i]) # find index of correct element
arr1[index] = element # swap
arr1[i] = arr2[i]
return swaps
#J.F. Sebastian and #Eyal Schneider's answer are pretty cool.
I got inspired on solving a similar problem: Calculate the minimum swaps needed to sort an array, e.g.: to sort {2,1,3,0}, you need minimum 2 swaps.
Here is the Java Code:
// 0 1 2 3
// 3 2 1 0 (0,3) (1,2)
public static int sortWithSwap(int [] a) {
Integer[] A = new Integer[a.length];
for(int i=0; i<a.length; i++) A[i] = a[i];
Integer[] B = Arrays.copyOf(mapping(A), A.length, Integer[].class);
int cycles = 0;
HashSet<Integer> set = new HashSet<>();
boolean newCycle = true;
for(int i=0; i<B.length; ) {
if(!set.contains(B[i])) {
if(newCycle) {
newCycle = false;
cycles++;
}
set.add(B[i]);
i = B[i];
}
else if(set.contains(B[i])) { // duplicate in existing cycles
newCycle = true;
i++;
}
}
// suppose sequence has n cycles, each cycle needs swap len(cycle)-1 times
// and sum of length of all cycles is length of sequence, so
// swap = sequence length - cycles
return a.length - cycles;
}
// a b b c
// c a b b
// 3 0 1 1
private static Object[] mapping(Object[] A) {
Object[] B = new Object[A.length];
Object[] ret = new Object[A.length];
System.arraycopy(A, 0, B, 0, A.length);
Arrays.sort(A);
HashMap<Object, Integer> map = new HashMap<>();
for(int i=0; i<A.length; i++) {
map.put(A[i], i);
}
for(int i=0; i<B.length; i++) {
ret[i] = map.get(B[i]);
}
return ret;
}
This seems like an edit distance problem, except that only transpositions are allowed.
Check out Damerau–Levenshtein distance pseudo code. I believe you can adjust it to count only the transpositions.

Resources