cppAcademy
FROM LEARNING TO COMPETING

Proficient.
Put your skills to the test.

Bulgarian Informatics Group B · 2009–2026

217 independently explained problems: 54 Municipal, 54 Regional and 109 National. Start with the easier tasks and work upwards. Difficulty labels are learning estimates, not official ratings; Group B also includes challenging national-level problems. National-round tasks shared by Groups A and B are included. Years follow Arena’s competition-season labels. Source clarifications and special grader requirements are noted on affected tasks.
GROUP B2016 · EasyUnbounded knapsack

Partitions into Powers of Two

National Olympiad — Municipal round (2016 season)

Submission name: sum.cpp

Problem summary

Count unordered representations of N as a sum of powers of two, allowing repeated summands and including 2^0.

Input

One integer N.

Output

The exact number of representations.

Constraints

1 ≤ N ≤ 3000.

Worked example

An independently prepared example for this explanation.

Input

6

Output

6

Solution analysis

  1. Treat each power of two not exceeding N as an unlimited coin denomination. Let ways[s] count representations of s using the denominations already processed.
  2. Initially ways[0]=1 for the empty sum. For each denomination p, scan sums s upward from p and add ways[s−p] to ways[s]. Upward order permits another copy of p; the outer denomination loop prevents counting different orders separately.
  3. For 6 the six partitions are 4+2, 4+1+1, 2+2+2, 2+2+1+1, 2+1+1+1+1, and six ones. At N=3000 the result is 6084830616290, which fits signed 64-bit arithmetic.

Why it works

When processing p, every representation either uses no p and was counted previously, or has a final copy of p whose removal leaves a representation of s−p using denominations up to p. These cases are disjoint and exhaustive. Induction over denominations proves the count.

Complexity: O(N log N) time and O(N) space.

Watch out. Use long long. Reversing the sum loop would allow each denomination only once.

Commented C++17 solution

An independently written complete program with standard headers.

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int n;
    cin>>n;
    vector<long long>ways(n+1,0);
    ways[0]=1;
    for(int power=1;power<=n;power*=2){
        // Ascending sums allow arbitrarily many copies of this power.
        for(int sum=power;sum<=n;++sum){
            ways[sum]+=ways[sum-power];
        }
    }
    cout<<ways[n]<<'\n';
}

Source: Arena Olimpiici ↗