Quantcast
Channel: CodeChef Discuss - latest questions
Viewing all articles
Browse latest Browse all 40121

ANUCBC - Editorial

$
0
0

PROBLEM LINK:

Practice
Contest

Author:Anudeep Nekkanti
Tester:Shiplu Hawlader and Mahbubul Hasan
Editorialist:Lalit Kundu

DIFFICULTY:

MEDIUM

PREREQUISITES:

Dynamic Programming
Precomputation

PROBLEM:

Given N numbers, and a number M, we need to find number of subsets such that sum of elements of subset is divisible by M.
1 <= N <= 100000
1 <= M <= 100
At most 3 test cases with 30 queries in each test. That is 90 queries at most.

EXPLANATION:

If you are not familiar with dynamic programming, read topcoder tutorial here first.
So, here we define a state DP[i][j] which stores the number of ways to choose subsets from A0...Ai such that subset sum modulo M is j.
Now,

 DP[i][j]= DP[i-1][j] + // we don't choose the i'th element   
           DP[i-1][(j-A[i])%M]  // we choose the i'th element

Our answer will be DP[N-1][0]. But here, complexity will be N*M for each query, which will time out.

The advantage here we have is that M<=100. A[i] doesn't matter to us. What matters is what A[i]%M is. So,

for i=0 to M-1:
     count[i]=number of A[j] such that A[j]%m=i

The above array count, can be calculated using hashing.
Again, we have to use dynamic programming.

We define a new state DP[i][j] which stores, the number of subsets which consists of only those Aj's whose modulo M is less than or equal to i, and subset sum modulo M is j.
choose(n,r) is number of ways to choose r elements out of n distinct elements ie. (n!)/((r!)*(n-r)!) Now,

DP[i][j] = 
DP[i-1][(j-i*0)%M]*choose(count[i],0)+// we don't pick any one of the count[i] choices we have.
DP[i-1][(j-i*1)%M]*choose(count[i],1)+// we can pick any one of the count[i] choices we have.
DP[i-1][(j-i*2)%M]*choose(count[i],2)+// we can pick any two of the count[i] choices we have.
.
.
.
DP[i-1][(j-i*count[i])%M]*choose(count[i],count[i])// we pick all of the count[i] choices we have

But, the complexity here will still remain N*M. We can rewrite the above as:

DP[i][j] = 
DP[i-1][(j-0)%M]*summation[k=0 to count[i], where (k*i)%M==0]{choose(count[i],k)} +
DP[i-1][(j-1)%M]*summation[k=0 to count[i], where (k*i)%M==1]{choose(count[i],k)} +
.
.
.
DP[i-1][(j-(M-1))%M]*summation[k=0 to count[i], where (k*i)%M==(M-1)]{choose(count[i],k)}

We can precompute all the summation terms above for each query in O(N).
So, complexity will be O(M*M*M) for each query.

AUTHOR'S AND TESTER'S SOLUTIONS:

To be updated soon.


Viewing all articles
Browse latest Browse all 40121

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>