#!/usr/bin/env python3
laps, change_time, core_round_time, tear_factor = map(int, input().split())

def sum_from_zero_to_exclusive_formula(n):
    """ Returns the sum 0 + 1 + 2 + ... + (n-1) """
    return n * (n - 1) // 2

def leap_time(laps):
    """ Returns the time it takes to complete the number of laps without changing tires """
    global core_round_time, tear_factor
    return laps * core_round_time + tear_factor * sum_from_zero_to_exclusive_formula(laps)

def total_time(tire_changes):
    """ Returns the total time with doing the provided number of tire changes """
    
    # A 'run' is some number of laps until changin tires again.
    runs = tire_changes + 1
    # Observation: It is always better to spread out changes as evenly
    # as possible, since the last lap in the run is most expensive.
    # Might not always be possible to distribute perfectly, so some runs
    # become one lap longer
    laps_per_run = laps // runs
    long_runs = laps % runs
    short_runs = runs - long_runs
    assert(short_runs*laps_per_run + long_runs*(laps_per_run + 1) == laps)
    time_short_run = leap_time(laps_per_run)
    time_long_run = leap_time(laps_per_run + 1)
    return short_runs * time_short_run + long_runs * time_long_run + change_time * tire_changes


# Binary search on the number of tire changes
lb = 0
ub = laps
# We binary search until the window is sufficiently small -- but
# it could happen (due to the way rounding happens) that two
# adjacent points are equal, even if none of them are the minimum
while lb + 10 < ub:
    third = (ub - lb) // 3
    lft = lb + third
    rgt = ub - third
    lft_ans = total_time(lft)
    rgt_ans = total_time(rgt)
    if lft_ans <= rgt_ans:
        ub = rgt
    if rgt_ans <= lft_ans:
        lb = lft
    
# Check every value in the resulting window
print(min(total_time(x) for x in range(lb, ub+1)))
