cppAcademy
FROM LEARNING TO COMPETING

Expert.
Put your skills to the test.

Bulgarian Informatics Group A · 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 A also includes challenging national-level problems. The 109 National-round tasks shared by Groups A and B retain their existing permanent URLs and explanations. Years follow Arena’s competition-season labels. Source clarifications and special grader requirements are noted on affected tasks.
GROUP A2012 · MediumDynamic programming

Expression

National Olympiad — Regional round (2012 season)

Submission name: expression.cpp

Problem summary

Count expressions consisting of operands from 2 through K and binary + or * operators, with no parentheses, whose value is N. Evaluate every operation strictly from left to right. Distinct sequences of symbols count separately.

Input

N and K.

Output

The exact number of expressions.

Constraints

2 < K < N < 80.

Worked example

Official statement sample.

Input

6 3

Output

5

Solution analysis

  1. Let ways[v] count expressions evaluating to v. Each single operand d contributes one expression at d. Every additional operand is attached to an existing expression by either +d or *d.
  2. Both operations strictly increase the current value because d≥2. Thus process values in increasing order and send ways[v] to v+d and v*d when the destination does not exceed N. A destination may receive contributions from both operations.
  3. For N=6,K=3 the five expressions are 2*2+2, 2+2+2, 3+3, 3*2, and 2*3. The expression 2+2*2 evaluates to 8 under the specified rule.

Why it works

Every nontrivial expression has a unique final operator, operand, and prefix expression. The transitions enumerate exactly these decompositions. Increasing value order ensures every prefix has already been counted.

Complexity: O(NKD) time and O(ND) space, where D is the maximum number of decimal digits in a count.

Watch out. Do not use ordinary multiplication precedence. Use exact integer arithmetic: the implementation stores counts as decimal strings, avoiding reliance on an unstated output bound.

Commented C++17 solution

An independently written complete program with standard headers.

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
string add(string a,const string&b){
    string result;
    int i=static_cast<int>(a.size())-1;
    int j=static_cast<int>(b.size())-1;
    int carry=0;
    while(i>=0||j>=0||carry){
        int digit=carry;
        if(i>=0){
            digit+=a[i--]-'0';
        }
        if(j>=0){
            digit+=b[j--]-'0';
        }
        result.push_back(char('0'+digit%10));
        carry=digit/10;
    }
    reverse(result.begin(),result.end());
    return result.empty()?"0":result;
}
int main(){
    int n,k;
    cin>>n>>k;
    vector<string>ways(n+1,"0");
    for(int d=2;d<=k;++d){
        ways[d]="1";
    }
    // Every transition goes to a strictly larger value.
    for(int v=2;v<=n;++v){
        for(int d=2;d<=k;++d){
            if(v+d<=n){
                ways[v+d]=add(ways[v+d],ways[v]);
            }
            if(v*d<=n){
                ways[v*d]=add(ways[v*d],ways[v]);
            }
        }
    }
    cout<<ways[n]<<'\n';
}

Source: Arena Olimpiici ↗