Finding number of subsets of an array that add up to a multiple of a specific number - c++

I have an array A of length N of negative as well as positive integers. I need to count the number of subsets in this array which add up to a multiple of a number M (or 0 (mod M))
For example:
Let A = {1,2,8,4,5}, M = 9,
Then, there are 4 such subsets:
{}: Empty set, corresponding to the multiple 0,
{1,8}: corresponding to the multiple 9,
{4,5}: corresponding to the multiple 9
{1,8,4,5}: corresponding to the multiple 18.
I thought of generating all possible multiples and then applying dynamic programming subset sum, but the constraints won't allow me that.
Constraints:
1 =< N <= 10^5,
1 =< M <= 100,
-10^9 =< each entry of array <=10^9
What should be my approach for this sort of problem?

You can solve this problem by dynamic programming, albeit extensive for large M and fast for small M. For each j satisfying 0 <=j <= M-1, and each integer k satisfying 0 < k <= N, let f(k,j) be the number of subsets of array elements between 1 and k that add up to give a sum of j mod M. Then to extend the counter f(k,j) to f(k+1,j') for all j' you just need to take the (k+1)th element X in your sequence and set f(k+1,j') = f(k,j') + f(k,j' - X mod M). When you iterate over all j satisfying 0 <= j <= M-1 for each k and then successively iterate over all k satisfying 0 <= k <= N, you will get your answer at f(N,0). Total complexity is O(MN), which for small M is basically linear in N, optimal.

Related

XOR of N elements after M timestamps of modification in them

There are N elements (numbered 1 to N). All are Zero initially. There
are M timestamps. In each timestamp, all the elements numbered between
L and R (both inclusive) increased by P. Find XOR of all elements
after M timestamps.
Input Format
The first line of the input contains a single integer T denoting the
number of test cases. The description of T test cases follows. The
first line contains two space-separated integers N, M. M lines follow.
The ith of these M lines contains three space-separated integers L, R,
P, describing the ith timestamp.
Constraints
1 < T < 100
1 < N < 1e16
0 < M < 1e4
1 < L < R < N
0 < P < 1e9
Sum of M over all test cases do not exceed 1e5
My approach
while(t--){
long long n,m;
cin>>n>>m;
long long a[n+1]={0};
while(m--){
ll x,y,p;
cin>>x>>y>>p;
for(int i=x;i<=y;i++)
a[i]=a[i]+p;
}
long long ans=0;
for(int i=1;i<=n;i++)
ans=ans^a[i];
cout<<ans<<"\n";
}
I can only come up with a bruteforce idea by which it seems impossible to solve because the constraints are too large.
How can I answer each test case in O(1) time. Thet Time limit for this question is only 1 sec.
The N elements can be viewed as members of an array.
If there are an even number of contiguous elements with the same value, the XOR of all these elements is zero.
If there are an odd number of contiguous elements with the same value X, the XOR of all these elements is X.
A solution to this problem is to iterate over the array, keeping track of how many repeated values of X there are prior to a change in value, and XOR'ing X to the running result if there were an odd number of repeats.
This can be computed without having to actually construct the array, nor loop over each element, by considering only the specified L and R indices from the input, which indicate the places where an array value may differ from its adjacent neighbor.
Here's an implementation in Python, which reads the input from stdin.
import sys
from collections import defaultdict
def getline():
return sys.stdin.readline().rstrip()
T = int(getline())
for _ in range(T):
N, M = map(int, getline().split())
lookup = defaultdict(int)
for _ in range(M):
L, R, P = map(int, getline().split())
lookup[L] += P
lookup[R + 1] -= P
lookup[N + 1] = 0
result = 0
X = 0
last_idx = 1
for idx in sorted(lookup):
count = idx - last_idx
if count & 1:
result ^= X
X += lookup[idx]
last_idx = idx
print(result)

Intuition behind storing the remainders?

I am trying to solve a question on LeetCode.com:
Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to the multiple of k, that is, sums up to n*k where n is also an integer. For e.g., if [23, 2, 4, 6, 7], k=6, then the output should be True, since [2, 4] is a continuous subarray of size 2 and sums up to 6.
I am trying to understand the following solution:
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
int n = nums.size(), sum = 0, pre = 0;
unordered_set<int> modk;
for (int i = 0; i < n; ++i) {
sum += nums[i];
int mod = k == 0 ? sum : sum % k;
if (modk.count(mod)) return true;
modk.insert(pre);
pre = mod;
}
return false;
}
};
I understand that we are trying to store: 0, (a/k), (a+b)/k, (a+b+c)/k, etc. into the hashSet (where k!=0) and that we do that in the next iteration since we want the subarray size to be at least 2.
But, how does this guarantee that we get a subarray whose elements sum up to k? What mathematical property guarantees this?
The set modk is gradually populated with all sums (considered modulo k) of contiguous sub-arrays starting at the beginning of the array.
The key observation is that:
a-b = n*k for some natural n iff
a-b ≡ 0 mod k iff
a ≡ b mod k
so if a contiguous sub-array nums[i_0]..nums[i_1], sums up to 0 modulo k, then the two sub-arrays nums[0]..nums[i_0] and nums[i_0 + 1]..nums[i_1] have the same sum modulo k.
Thus it's enough if two distinct sub-arrays starting at the beginning of the array have the same sum, modulo k.
Luckily, there are only k such values, so you only need to use a set of size k.
Some nitpicks:
if n > k, you're going to have an appropriate sub-array anyway (the pigeon-hole principle), so the loop will actually never iterate more than k+1 times.
There should not be any sort of class involved here, that makes no sense.
contiguous, not continuous. Arrays and sub-arrays are discrete and can't be continuous...
module base k of sum is equivalent to the module k of sum of the modules base k
(a+b)%k = (a%k + b%k) % k
(23 + 2) % 6 = 1
( (23%6) + (2%6) ) % 6 = (5 + 2) % 6 = 1
modk stores all modules that you calculated iteratively. If at iteration i you get a repeated module calculated at i-m that means that you added a subsequence of m elements which sum is multiple of k
i=0 nums[0] = 23 sum = 23 sum%6 = 5 modk = [5]
i=1 nums[1] = 2 sum = 25 sum%6 = 1 modk = [5, 1]
i=2 nums[2] = 4 sum = 29 sum%6 = 5 5 already exists in modk (4+2)%6 =0

[Competitive Programming]:How do I optimise this brute force method? [duplicate]

If n numbers are given, how would I find the total number of possible triangles? Is there any method that does this in less than O(n^3) time?
I am considering a+b>c, b+c>a and a+c>b conditions for being a triangle.
Assume there is no equal numbers in given n and it's allowed to use one number more than once. For example, we given a numbers {1,2,3}, so we can create 7 triangles:
1 1 1
1 2 2
1 3 3
2 2 2
2 2 3
2 3 3
3 3 3
If any of those assumptions isn't true, it's easy to modify algorithm.
Here I present algorithm which takes O(n^2) time in worst case:
Sort numbers (ascending order).
We will take triples ai <= aj <= ak, such that i <= j <= k.
For each i, j you need to find largest k that satisfy ak <= ai + aj. Then all triples (ai,aj,al) j <= l <= k is triangle (because ak >= aj >= ai we can only violate ak < a i+ aj).
Consider two pairs (i, j1) and (i, j2) j1 <= j2. It's easy to see that k2 (found on step 2 for (i, j2)) >= k1 (found one step 2 for (i, j1)). It means that if you iterate for j, and you only need to check numbers starting from previous k. So it gives you O(n) time complexity for each particular i, which implies O(n^2) for whole algorithm.
C++ source code:
int Solve(int* a, int n)
{
int answer = 0;
std::sort(a, a + n);
for (int i = 0; i < n; ++i)
{
int k = i;
for (int j = i; j < n; ++j)
{
while (n > k && a[i] + a[j] > a[k])
++k;
answer += k - j;
}
}
return answer;
}
Update for downvoters:
This definitely is O(n^2)! Please read carefully "An Introduction of Algorithms" by Thomas H. Cormen chapter about Amortized Analysis (17.2 in second edition).
Finding complexity by counting nested loops is completely wrong sometimes.
Here I try to explain it as simple as I could. Let's fix i variable. Then for that i we must iterate j from i to n (it means O(n) operation) and internal while loop iterate k from i to n (it also means O(n) operation). Note: I don't start while loop from the beginning for each j. We also need to do it for each i from 0 to n. So it gives us n * (O(n) + O(n)) = O(n^2).
There is a simple algorithm in O(n^2*logn).
Assume you want all triangles as triples (a, b, c) where a <= b <= c.
There are 3 triangle inequalities but only a + b > c suffices (others then hold trivially).
And now:
Sort the sequence in O(n * logn), e.g. by merge-sort.
For each pair (a, b), a <= b the remaining value c needs to be at least b and less than a + b.
So you need to count the number of items in the interval [b, a+b).
This can be simply done by binary-searching a+b (O(logn)) and counting the number of items in [b,a+b) for every possibility which is b-a.
All together O(n * logn + n^2 * logn) which is O(n^2 * logn). Hope this helps.
If you use a binary sort, that's O(n-log(n)), right? Keep your binary tree handy, and for each pair (a,b) where a b and c < (a+b).
Let a, b and c be three sides. The below condition must hold for a triangle (Sum of two sides is greater than the third side)
i) a + b > c
ii) b + c > a
iii) a + c > b
Following are steps to count triangle.
Sort the array in non-decreasing order.
Initialize two pointers ‘i’ and ‘j’ to first and second elements respectively, and initialize count of triangles as 0.
Fix ‘i’ and ‘j’ and find the rightmost index ‘k’ (or largest ‘arr[k]‘) such that ‘arr[i] + arr[j] > arr[k]‘. The number of triangles that can be formed with ‘arr[i]‘ and ‘arr[j]‘ as two sides is ‘k – j’. Add ‘k – j’ to count of triangles.
Let us consider ‘arr[i]‘ as ‘a’, ‘arr[j]‘ as b and all elements between ‘arr[j+1]‘ and ‘arr[k]‘ as ‘c’. The above mentioned conditions (ii) and (iii) are satisfied because ‘arr[i] < arr[j] < arr[k]'. And we check for condition (i) when we pick 'k'
4.Increment ‘j’ to fix the second element again.
Note that in step 3, we can use the previous value of ‘k’. The reason is simple, if we know that the value of ‘arr[i] + arr[j-1]‘ is greater than ‘arr[k]‘, then we can say ‘arr[i] + arr[j]‘ will also be greater than ‘arr[k]‘, because the array is sorted in increasing order.
5.If ‘j’ has reached end, then increment ‘i’. Initialize ‘j’ as ‘i + 1′, ‘k’ as ‘i+2′ and repeat the steps 3 and 4.
Time Complexity: O(n^2).
The time complexity looks more because of 3 nested loops. If we take a closer look at the algorithm, we observe that k is initialized only once in the outermost loop. The innermost loop executes at most O(n) time for every iteration of outer most loop, because k starts from i+2 and goes upto n for all values of j. Therefore, the time complexity is O(n^2).
I have worked out an algorithm that runs in O(n^2 lgn) time. I think its correct...
The code is wtitten in C++...
int Search_Closest(A,p,q,n) /*Returns the index of the element closest to n in array
A[p..q]*/
{
if(p<q)
{
int r = (p+q)/2;
if(n==A[r])
return r;
if(p==r)
return r;
if(n<A[r])
Search_Closest(A,p,r,n);
else
Search_Closest(A,r,q,n);
}
else
return p;
}
int no_of_triangles(A,p,q) /*Returns the no of triangles possible in A[p..q]*/
{
int sum = 0;
Quicksort(A,p,q); //Sorts the array A[p..q] in O(nlgn) expected case time
for(int i=p;i<=q;i++)
for(int j =i+1;j<=q;j++)
{
int c = A[i]+A[j];
int k = Search_Closest(A,j,q,c);
/* no of triangles formed with A[i] and A[j] as two sides is (k+1)-2 if A[k] is small or equal to c else its (k+1)-3. As index starts from zero we need to add 1 to the value*/
if(A[k]>c)
sum+=k-2;
else
sum+=k-1;
}
return sum;
}
Hope it helps........
possible answer
Although we can use binary search to find the value of 'k' hence improve time complexity!
N0,N1,N2,...Nn-1
sort
X0,X1,X2,...Xn-1 as X0>=X1>=X2>=...>=Xn-1
choice X0(to Xn-3) and choice form rest two item x1...
choice case of (X0,X1,X2)
check(X0<X1+X2)
OK is find and continue
NG is skip choice rest
It seems there is no algorithm better than O(n^3). In the worst case, the result set itself has O(n^3) elements.
For Example, if n equal numbers are given, the algorithm has to return n*(n-1)*(n-2) results.

longest contiguous subsequence such that twice the number of zeroes is less than equal to thrice the number of ones

I was trying to solve this problem from hacker rank I tried the brute fore solution but it doesnt seem to work. Can some one gimme an idea to solve this problem efficiently.
https://www.hackerrank.com/contests/sep13/challenges/sherlock-puzzle
Given a binary string (S) which contains ‘0’s and ‘1’s and an integer K,
find the length (L) of the longest contiguous subsequence of (S * K) such that twice the number of zeroes is <= thrice the number of ones (2 * #0s <= 3 * #1s) in that sequence.
S * K is defined as follows: S * 1 = S
S * K = S + S * (K - 1)
Input Format
The first (and only) line contains an integer K and the binary string S separated by a single space.
Constraints
1 <= |S| <= 1,000,000
1 <= K <= 1,000,000
Output Format
A single integer L - the answer to the test case
Here's a hint:
Let's first suppose K = 1 and that S looks like (using a dot for 0):
..1...11...11.....111111....111....
e f b a c d
The key is to note that if the longest acceptable sequence contains a 1 it will also contain any adjacent ones. For example, if the longest sequence contains the 1 at a, it will also contain all of the ones between b and c (inclusive).
So you only have to analyze the sequence at the points where the blocks of ones are.
The main question is: if you start at a certain block of ones, can you make it to the next block of ones? For instance, if you start at e you can make it to the block at f but not to b. If you start at b you can make it to the block at d, etc.
Then generalize the analysis for K > 1.
Brute force obviously won't work since it's O((n * k) ** 2). I will use python style list comprehensions in this answer. You'll need an array t = [3 if el == "1" else - 2 for el in S]. Now if you use the p[i] = t[0] + ... + t[i] array you can see that in the k == 1 case you are basically looking for a pair (i, j), i < j such that p[j] - (p[i - 1] if i != 0 else 0) >= 0 is true and j - i is maximal among
these pairs. Now for each i in 0..n-1 you have to find find it's j pair such that the above is maximal. This can be done in O(log n) for a specific i so this gives and O(n log n) solution for the k == 1 case. This can be extended to an O(n log n) solution for the general case(there is a trick to find the largest block that can be covered). Also there is an O(n) solution to this problem but you need to further examine the p sequence for that. I don't suggest to write a solution in a scripting language though. Even the O(n) solution times out in python...

Maximum subset which has no sum of two divisible by K

I am given the set {1, 2, 3, ... ,N}. I have to find the maximum size of a subset of the given set so that the sum of any 2 numbers from the subset is not divisible by a given number K. N and K can be up to 2*10^9 so i need a very fast algorithm. I only came up with an algorithm of complexity O(K), which is slow.
first calculate all of the set elements mod k.and solve simple problem:
find the maximum size of a subset of the given set so that the sum of any 2 numbers from the subset is not equal by a given number K.
i divide this set to two sets (i and k-i) that you can not choose set(i) and set(k-i) Simultaneously.
int myset[]
int modclass[k]
for(int i=0; i< size of myset ;i++)
{
modclass[(myset[i] mod k)] ++;
}
choose
for(int i=0; i< k/2 ;i++)
{
if (modclass[i] > modclass[k-i])
{
choose all of the set elements that the element mod k equal i
}
else
{
choose all of the set elements that the element mod k equal k-i
}
}
finally you can add one element from that the element mod k equal 0 or k/2.
this solution with an algorithm of complexity O(K).
you can improve this idea with dynamic array:
for(int i=0; i< size of myset ;i++)
{
x= myset[i] mod k;
set=false;
for(int j=0; j< size of newset ;j++)
{
if(newset[j][1]==x or newset[j][2]==x)
{
if (x < k/2)
{
newset[j][1]++;
set=true;
}
else
{
newset[j][2]++;
set=true;
}
}
}
if(set==false)
{
if (x < k/2)
{
newset.add(1,0);
}
else
{
newset.add(0,1);
}
}
}
now you can choose with an algorithm of complexity O(myset.count).and your algorithm is more than O(myset.count) because you need O(myset.count) for read your set.
complexity of this solution is O(myset.count^2),that you can choose algorithm depended your input.with compare between O(myset.count^2) and o(k).
and for better solution you can sort myset based on mod k.
I'm assuming that the set of numbers is always 1 through N for some N.
Consider the first N-(N mod K) numbers. The form floor(N/K) sequences of K consecutive numbers, with reductions mod K from 0 through K-1. For each group, floor(K/2) have to be dropped for having a reduction mod K that is the negation mod K of another subset of floor(K/2). You can keep ceiling(K/2) from each set of K consecutive numbers.
Now consider the remaining N mod K numbers. They have reductions mod K starting at 1. I have not worked out the exact limits, but if N mod K is less than about K/2 you will be able to keep all of them. If not, you will be able to keep about the first ceiling(K/2) of them.
==========================================================================
I believe the concept here is correct, but I have not yet worked out all the details.
==========================================================================
Here is my analysis of the problem and answer. In what follows |x| is floor(x). This solution is similar to the one in #Constantine's answer, but differs in a few cases.
Consider the first K*|N/K| elements. They consist of |N/K| repeats of the reductions modulo K.
In general, we can include |N/K| elements that are k modulo K subject to the following limits:
If (k+k)%K is zero, we can include only one element that is k modulo K. That is the case for k=0 and k=(K/2)%K, which can only happen for even K.
That means we get |N/K| * |(K-1)/2| elements from the repeats.
We need to correct for the omitted elements. If N >= K we need to add 1 for the 0 mod K elements. If K is even and N>=K/2 we also need to add 1 for the (K/2)%K elements.
Finally, if M(N)!=0 we need to add a partial or complete copy of the repeat elements, min(N%K,|(K-1)/2|).
The final formula is:
|N/K| * |(K-1)/2| +
(N>=K ? 1 : 0) +
((N>=K/2 && (K%2)==0) ? 1 : 0) +
min(N%K,|(K-1)/2|)
This differs from #Constantine's version in some cases involving even K. For example, consider N=4, K=6. The correct answer is 3, the size of the set {1, 2, 3}. #Constantine's formula gives |(6-1)/2| = |5/2| = 2. The formula above gets 0 for each of the first two lines, 1 from the third line, and 2 from the final line, giving the correct answer.
formula is
|N/K| * |(K-1)/2| + ost
ost =
if n<k:
ost =0
else if n%k ==0 :
ost =1
else if n%k < |(K-1)/2| :
ost = n%k
else:
ost = |(K-1)/2|
where |a/b|
for example |9/2| = 4 |7/2| = 3
example n = 30 , k =7 ;
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
1 2 3 |4| 5 6 7. - is first line .
8 9 10 |11| 12 13 14 - second line
if we getting first 3 number in each line we may get size of this subset. also we may adding one number from ( 7 14 28)
getting first 3 number (1 2 3) is a number |(k-1)/2| .
a number of this line is |n/k| .
if there is not residue we may add one number (for example last number).
if residue < |(k-1)/2| we get all number in last line
else getting |(K-1)/2|.
thanks for exception case.
ost = 0 if k>n
n,k=(raw_input().split(' '))
n=int(n)
k=int(k)
l=[0 for x in range(k)]
d=[int(x) for x in raw_input().split(' ')]
flag=0
for x in d:
l[x%k]=l[x%k]+1
sum=0
if l[0]!=0:
sum+=1
if (k%2==0):
sum+=1
if k==1:
print 1
elif k==2:
print 2
else:
i=1
j=k-1
while i<j:
sum=sum+(l[i] if l[i]>=l[j] else l[j])
i=i+1
j=j-1
print sum
This is explanation to ABRAR TYAGI and amin k's solution.
The approach to this solution is:
Create an array L with K buckets and group all the elements from the
input array D into the K buckets. Each bucket L[i] contains D's elements such that ( element % K ) = i.
All the elements that are individually divisible by K are in L[0]. So
only one of these elements (if any) can belong in our final (maximal)
subset. Sum of any two of these elements is divisible by K.
If we add an element from L[i] to an element in L[K-i] then the sum is divisible by K. Hence we can add elements from only one of these buckets to
our final set. We pick the largest bucket.
Code:
d is the array containing the initial set of numbers of size n. The goal of this code is to find the count of the largest subset of d such that the sum of no two integers is divisible by 2.
l is an array that will contain k integers. The idea is to reduce each (element) in array d to (element % k) and save the frequency of their occurrences in array l.
For example, l[1] contains the frequency of all elements % k = 1
We know that 1 + (k-1) % k = 0 so either l[1] or l[k-1] have to be discarded to meet the criteria that sum of no two numbers % k should be 0.
But as we need the largest subset of d, we choose the larger of l[1] and l[k-1]
We loop through array l such that for (i=1; i<=k/2 && i < k-i; i++) and do the above step.
There are two outliers. The sum of any two numbers in the l[0] group % k = 0. So add 1 if l[0] is non-zero.
if k is even, the loop does not handle i=k/2, and using the same logic as above increment the count by one.