CodeChef is a non-commercial competitive programming community
Login
Username (New User? Signup) Password (Forgot Password?)
Signup
Login or
Signup with
Connect
Note
  • Publicize your achievements on your Facebook Wall.
  • Challenge your friends or ask them for help.

Site Navigation

  • PRACTICE
    • Easy
    • Medium
    • Hard
    • Challenge
    • Peer
  • COMPETE
    • All Contests
    • June Long 2012
    • May Cook-Off
    • May Long 2012
  • DISCUSS
    • Forums
    • Blog
    • Wiki
    • Facebook
    • Twitter
  • COMMUNITY
    • CodeChef Meetups
    • Campus Chapters
    • Host your Contest
    • User Groups
    • CodeChef TechTalks
    • All Educational Initiatives
  • HELP
    • Frequently Asked Questions
    • FAQ for problem setters
    • Problem Setting
    • Tutorials
    • Long Contest Ranks
    • Short Contest Ranks
    • Event Calendar
  • ABOUT
    • About CodeChef
    • Team CodeChef
    • Press Room
    • CodeChef Financials
    • CodeChef Sponsorships
    • CEO's Corner
    • Contact Us
    • About Directi
Home » Wiki » Tutorial for Paying Up

Tutorial for Paying Up

Hello,

The problem "Paying Up" was one of the easy ones in the March 2009 contest on Codechef. It is considered an easy problem, because it has a couple of approaches that work. The problem statement boils down to finding a subset of banknotes such that their sum is exactly equal to a certain value. Now, this problem is somewhat similar to the knapsack problem which asks for ways to fill up a knapsack of a certain size optimally with the given blocks. There is a solution based on dynamic programming for this problem, but we will be taking up a solution which makes good use of the way integers are represented in binary to solve this problem.

Now, the limit on the number of banknotes is 'n'. Let us see how many subsets exist for these banknotes. For finding the number of subsets, we see that for every banknote, we have two choices, either to choose it in our calculation for the sum of notes or to ignore it in calculating the sum. Thus, we have 2 options per banknote and 'n' banknotes. So, the total number of subsets thus becomes 2^n where ^ represents the power operation. The number of subsets are small enough for us to bruteforce through them and the program to run in time.

An interesting way to generate all subsets of 'n' objects when 'n' is considerably small (n <= 20) is to use the properties of how unsigned integers are stored. Consider the number 2^n. This number is represented in binary form as '10000...0', that is, 1 followed by n 0s. Also, any number containing a 1 at the same position will surely be greater than 2^n. Thus, all numbers below 2^n do not have a 1 in a position greater than or equal to 'n' starting from the LSB. By induction, we can do the same for values of n = n-1 and n-2 and so on. Thus, we can see that any number between 2^(n-1) and 2^n will have a 1 in the position n-1. Extending this logic, we can say that if we consider the numbers from 1 to 2^n, we would be considering all possible ways in which we can choose some objects from 'n' objects.

For example, consider n = 3, so 2^n = 8. Let us list 'i' and its binary representation
i    Binary representation using 'n' bits
0    000
1    001
2    010
3    011
4    100
5    101
6    110
7    111

As you can see, if we consider that 1 means that we have selected object at that position and 0 means that we have not selected the object at that position, we can get all possible subsets of 'n' objects by looping over numbers from 1 to 2^n.

For calculating the sum of the subset represented by 'i', we loop from 0 to 'n' and we check whether the corresponding bit is set in the value for 'i' or not. If it is, we include that object in calculating our sum else we don't. In this way, we can get the sum for all possible subsets of the 'n' objects.

This is exactly what we need for this problem. After taking in the number of objects, we loop 'i' from 1 to 2^n incrementing the value of 'i' by 1 at every stage to give us a new subset. Then for a particular value of 'i', we loop 'j' from 0 to n and check if the bit at that particular value is set or not. Languages like C / C++ provide bit-wise operators for leftshift and rightshift. For checking if the bit is set at position 'j'(starting from 0) we can just check if the value of (i & (1<<j)) is 0. If it is 0, then the bit is not set, while if it is greater than 0, then the bit is set. Alternatively, we can also loop from 0 to n and at each stage check whether 'i' modulo 2 is equal to 1 or not. If it is 1, then the bit at that position is set, else it's not. Then we divide 'i' by 2 and proceed. At the end of the 'n' iterations, 'i' will equal 0. The problem with this appraoch is that the modulo operations take much more time compared to the bitwise operations. Thus, now that we know how to check if the bit is set, we initialize a value 'sum' equal to 0 at the start of the 'n' iterations for a value of 'i' and if the bit at position 'j' is set, we add the corresponding banknote value to 'sum' else we don't. At the end of these iterations, we check if the value of 'sum' equals the required value. If it does, then we have found a subset with the required sum and so we print a "Yes" and exit. Else, if at the end of 2^n iterations of 'i' we don't have a subset with the required sum, then we print a "No" and exit.

The program should look something like this :

[code]

Start

Take in the value of 'n' and the required value of sum 'm'

Take in all the values for the banknotes in array 'd[]'

For i = 1 and i < (2^n)

sum = 0

For j = 0 and j < n

if jth bit of i is set

sum = sum + d[j]

if sum equals m

print Yes and return

Print No and return

[/code]


Comments

  • Login or Register to post a comment.

can smone fnd error in my

gauravgaba @ 31 Dec 2009 05:13 PM

can smone fnd error in my code i dnt why it's giving wrong answer...............#include<stdio.h>


int main(void) {

int t,n,m;
int i,j,s,a[20];
//clrscr();

scanf("%d",&t);

while(t--) {

scanf("%d %d",&n,&m);

for(i=0;i<n;i++)
scanf("%d",&a[i]);

for(i=1;i<(1<<n);i++) {

s=0;

for(j=0;j<n;j++)
if(i&(1<<j)>0)
s=s+a[j];

if(s==m) {
printf("YESn");
goto end;
}


}


printf("NOn");

end : continue;

}
return 0;
}

Your problem fails the sample

triplem @ 1 Jan 2010 04:45 AM

Your problem fails the sample input. And in fact, every single case. Read the problem statement again.

very nice tutorial . . .

Geniusguy @ 2 Jan 2010 02:57 PM

very nice tutorial . . . .learned some new efficient ways to play with number of the form of power of 2 . . .thanks a lot CodeChef ! ! ! :)

the application of binary

rajesh3646 @ 29 Jan 2010 10:41 PM

the application of binary representation is applied.its nice to see

can anyone plz check the

abhimanyu srivastava @ 12 Feb 2010 04:02 PM

can anyone plz check the error in it..it is giving runtime error...

#include<iostream>
using namespace std;
void ins(int*,int);
int main()
{
int t,n,m,c=0,i,j;
int *b=new int[t];
for(i=0;i<t;i++)
b[i]=0;
cin>>t;
while(t>0)
{
cin>>n>>m;
int *a=new int[n];
for(i=0;i<n;i++)
{
cin>>a[i];
}
ins(a,n);
int sum=0;
for(i=0;i<n;i++)
{
if(b[c]!=1)
{
sum=a[i];
for(j=i+1;j<n;j++)
{
if(sum+a[j]<m)
{
sum=sum+a[j];
}
else if(sum+a[j]>m)
continue;
else if(sum+a[j]==m)
{
b[c]=1;
break;
}
}
}
}
c++;
t--;
}
for(i=0;i<c;i++)
{
if(b[i]==0)
cout<<"n"<<"NO";
else
cout<<"n"<<"YES";
}
}

void ins(int a[] ,int n)
{
int i,j,key1;
for(j=1;j<n;j++)
{ 
key1=a[j];
i=j-1;
while(key1>a[i]&&i>=0)
{
a[i+1]=a[i];
i--;
}
i++;
a[i]=key1;
}        
}

#include<iostream>#include<cm

arjunnu @ 19 Feb 2010 05:32 PM

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int i,n,m,sum,temp,t,me;
cout<<"Enter number of test cases:";
cin>>t;
for(int p=0;p<t;p++)
{
int flag=0;
cout<<"nEnter the number of notes in wallet:";
cin>>n;
cout<<"nEnter the amount you want:";
cin>>m;
cout<<"nEnter the values of the "<<n<<" notes you have:n";
int *note;
note = new int [n];
int iarr[n];
for (i=0;i<n;i++)
{
cin>>note[i];
iarr[i]=0;
}    
for (i=0;i<(1<<n);i++)
{
me=i;
for(temp=0;temp<n;temp++)
{
iarr[temp]=me%2;
me=me/2;
}   
sum=0;
for(int j=0;j<n;j++)
{
if(iarr[j]==1)
sum=sum+note[j];
}
if (sum==m)
{
cout<<"Yesn";
flag=1; 
break;
}                         
}        
if(flag==0)
cout<<"No!n";
}
return 0;
}

 

some one expalin the problem with the code :(

Please don't post code. Read

triplem @ 20 Feb 2010 02:15 AM

Please don't post code. Read the FAQ.

great tutorial,, THANKS A

Bhat Chandru @ 9 Mar 2010 02:42 PM

great tutorial,, THANKS A MILLION!!

nice tutorial this approach

theharbringer @ 4 Jun 2010 05:00 PM

nice tutorial this approach is way better than mine

Excellent technique of

javadecoder @ 15 Jun 2010 05:59 PM

Excellent technique of generating subsets!

what will be complexity of

AnoopNarang @ 12 Jul 2010 04:40 AM

what will be complexity of this algorithm in big O notation??

what will be complexity of d

AnoopNarang @ 12 Jul 2010 04:40 AM

what will be complexity of d above algorithm in big O notation??

I always had a problem with

puneet_50 @ 25 Sep 2010 11:11 AM

I always had a problem with permutations.Thanks for this technique.

This will help me a lot!

"any number containing a 1 at

haafmaad @ 2 Oct 2010 04:28 PM

"any number containing a 1 at the same position will surely be greater than 2^n"

ehat does that mean??

whats wrong with this

knightyau @ 20 Oct 2010 08:34 PM

whats wrong with this example?can anyone explain?

#include <iostream>
using namespace std;
int main()
{
int a[2] = {1,2};
int sum = 0;
for(int i=1;i<4;i++)
{   
sum = 0;
for(int j=0;j<2;j++)
{
if(i&(1<<j)!=0)
{
sum += a[j];
}
}
cout << sum <<" ";
}
}

@ashiqul mostofa :  supoose

mayursharma @ 4 Nov 2010 11:38 AM

@ashiqul mostofa :  supoose any number < 2^n ( take any n) . let 5 be a number and n=2. its binary reperesnetation is 101 . here 1 is at 2nd position . it is olwayz be greater than a number   2^2 i.e 4 .

 

hello i m not getting y we

mayursharma @ 4 Nov 2010 12:08 PM

hello i m not getting y we add d[i] to sum only when i & (1<<j) is > 0 .

i hav read this tutorial 2-3 times...but i m not able to get that point... wud nay1 please explore  more  about it...:)

The Complexity  of the above

s1h33p @ 29 Dec 2010 12:50 PM

The Complexity  of the above solution is still high we need better solution to it.

worse case O(n2^n)

best case O(2^n)

note*  Not sure if i am correct. try to find notaion by usrself, and post the correction if any.

 

nice tutorial :)

jaipurchamp_1 @ 5 Jan 2011 11:53 AM

nice tutorial :)

Umm, i really think my logic

anantc @ 18 Mar 2011 07:54 PM

Umm, i really think my logic is correct. Can somebody please check my solution ?

http://www.codechef.com/viewsolution/491186

Help will be really appreciated

 

 

Thanks :D

awesome solution!!!!!

aayush123 @ 6 Apr 2011 02:36 PM

awesome solution!!!!!

BRAVO!!!  OUTSTANDING, i cant

s1h33p @ 22 Apr 2011 05:28 PM

BRAVO!!!  OUTSTANDING, i cant express but i am so imressed with this technique,  i spent about 3 days on this question for finding the solustion on my own, but this technique is really awsome.

really awsome tutorial, a lot

princeofpersia @ 26 Apr 2011 12:19 PM

really awsome tutorial,

a lot of thanks.

from sys import * def

rishimukherjee @ 7 Aug 2011 12:28 AM
from sys import * def paying(D, m, n): for i in range(1, 2**n+1): sum = 0 for j in range(0, n): if (i& (1<

_/\_ Bow Bow. Kudos!! Great

chouhan @ 10 Aug 2011 01:16 AM
_/_ Bow Bow. Kudos!! Great tutorial, taught me a lot of new things which I hope I would never forget. Thanks CodeChef. Best regards -DV

awesome!!

riseabove @ 1 Oct 2011 11:10 PM
awesome!!

amazing tutorials :)

mohakr @ 13 Oct 2011 02:00 PM
amazing tutorials :)

this IS

selfcompiler @ 26 Oct 2011 08:58 AM
this IS awesome.............this gives me great pleasure...........thanx......codechef.........

#include #include main() { i

selfcompiler @ 26 Oct 2011 09:50 AM
#include #include main() { int i,j,n,t,m; int sum; scanf("%d",&t); while(t--) { sum=0; scanf("%d %d",&n,&m); int d[n]; for(i=0;i

what is the problem in above

selfcompiler @ 26 Oct 2011 09:51 AM
what is the problem in above code plz ...see

#include #include main() {

selfcompiler @ 26 Oct 2011 11:23 AM
#include #include main() { int j,n,t,m; int sum,c; long int i; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&m); int d[n]; for(i=0;i

Why the value of sum is not

hasan_king @ 8 Feb 2012 01:31 AM
Why the value of sum is not come in float? #include #include main() { clrscr(); int a,b; float sum; printf("nEnter the value of a:"); scanf("%d",&a); printf("nEnter the value of b:"); scanf("%d",&b); sum=(a+b)/2; printf("n sum = %f",sum); getch(); return(0); }

#include #include #include in

hitesh29jan91 @ 22 Feb 2012 01:45 PM
#include #include #include int main() { unsigned int value=0; int i=0,j=0,n=0,sum=0,m=0,mid=0; int banknote[50][3]; printf("\n Enter The Number : "); scanf(" %d",&n); printf("\n Enter The Value of Sum : "); scanf(" %d",&m); for(i=0;i=0;j--) { mid=value%2; value=value/2; banknote[i][j]=mid; if(mid==1) { sum=sum+i; } } if(sum==m) { printf("n Yes "); } else { continue; } } getch(); return 0; }

do backtraking in this

hellodear @ 5 Apr 2012 12:00 AM
do backtraking in this question
CodeChef is a non-commercial competitive programming community
  • About CodeChef
  • About Directi
  • CEO's Corner
  • C-Programming
  • Programming Languages
  • Contact Us
© 2009 Directi Group. All Rights Reserved. CodeChef uses SPOJ © by Sphere Research Labs
In order to report copyright violations of any kind, send in an email to copyright@codechef.com
CodeChef a product of Directi
The time now is:
CodeChef - A Platform for Aspiring Programmers

CodeChef was created as a platform to help programmers make it big in the world of algorithms, computer programming and programming contests. At CodeChef we work hard to revive the geek in you by hosting a programming contest at the start of the month and another smaller programming challenge in the middle of the month. We also aim to have training sessions and discussions related to algorithms, binary search, technicalities like array size and the likes. Apart from providing a platform for programming competitions, CodeChef also has various algorithm tutorials and forum discussions to help those who are new to the world of computer programming.

Practice Section - A Place to hone your 'Computer Programming Skills'

Try your hand at one of our many practice problems and submit your solution in a language of your choice. Our programming contest judge accepts solutions in over 35+ programming languages. Preparing for coding contests were never this much fun! Receive points, and move up through the CodeChef ranks. Use our practice section to better prepare yourself for the multiple programming challenges that take place through-out the month on CodeChef.

Compete - Monthly Programming Contests and Cook-offs

Here is where you can show off your computer programming skills. Take part in our 10 day long monthly coding contest and the shorter format Cook-off coding contest. Put yourself up for recognition and win great prizes. Our programming contests have prizes worth up to Rs.20,000 and $700lots more CodeChef goodies up for grabs.

Discuss

Are you new to computer programming? Do you need help with algorithms? Then be a part of CodeChef's Forums and interact with all our programmers - they love helping out other programmers and sharing their ideas. Have discussions around binary search, array size, branch-and-bound, Dijkstra's algorithm, Encryption algorithm and more by visiting the CodeChef Forums and Wiki section.

CodeChef Community

As part of our Educational initiative, we give institutes the opportunity to associate with CodeChef in the form of Campus Chapters. Hosting online programming competitions is not the only feature on CodeChef. You can also host a coding contest for your institute on CodeChef, organize an algorithm event and be a guest author on our blog.

Go For Gold

The Go for Gold Initiative was launched about a year after CodeChef was incepted, to help prepare Indian students for the ACM ICPC World Finals competition. In the run up to the ACM ICPC competition, the Go for Gold initiative uses CodeChef as a platform to train students for the ACM ICPC competition via multiple warm up contests. As an added incentive the Go for Gold initiative is also offering over Rs.8 lacs to the Indian team that beats the 29th position at the ACM ICPC world finals. Find out more about the Go for Gold and the ACM ICPC competition here.

Domain Name Registration, Web hosting, and Website Design provided by BigRock.com