#define _USE_MATH_DEFINES #pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include #include #include #include #include #include //#include using namespace std; //using namespace atcoder; #define LP(I,S,G) for (long long int I = (S); I < (G); ++I) #define IN(X) for (int in = 0; in < X.size(); in++)cin >> X[in] #define OUT(X) for (int in = 0; in < X.size(); in++)cout << X[in]<<" " #define SORT(X) sort((X).begin(), (X).end()) #define CSORT(X,Y) sort(X.begin(), X.end(),Y) #define COPY(X,Y) copy(X.begin(), X.end(), Y.begin()) #define ALL(X,Y) for (auto &(X) :(Y)) #define FULL(a) (a).begin(),(a).end() #define BFS(Q,S) for(Q.push(S);Q.size()!=0;Q.pop()) typedef long long int ll; typedef unsigned long long int ull; long long int M = 998244353; chrono::system_clock::time_point starttime; using namespace std::chrono; inline float getTime() { return duration_cast(system_clock::now() - starttime).count(); } int dx[] = { -1,0,1,0 }, dy[] = { 0,1,0,-1 }; ll MAX(ll A, ll B) { return ((A) > (B) ? (A) : (B)); } ll MIN(ll A, ll B) { return ((A) < (B) ? (A) : (B)); } inline long long int xor128() { static long long int x = 123456789, y = 362436069, z = 521288629, w = 88675123; long long int t = (x ^ (x << 11)); x = y; y = z; z = w; return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))); } struct HashPair { //注意 constがいる template size_t operator()(const pair &p) const { //first分をハッシュ化する auto hash1 = hash{}(p.first); //second分をハッシュ化する auto hash2 = hash{}(p.second); //重複しないようにハッシュ処理 size_t seed = 0; seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2); seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2); return seed; } }; int main() { ll n, a, b, c; cin >> n >> a >> b >> c; vector dp(n + 1, a*n), kai(n + 1, 1); dp[1] = 0; ll border = a * n; ll ku = -1; priority_queue, vector>, greater>> pq; pq.push({ 0,1 }); LP(i, 1, n + 1) { if (kai[i - 1] * i >= n && ku == -1)ku = i; kai[i] = (kai[i - 1] * i) % n; } while (pq.size() != 0) { auto[d, now] = pq.top(); pq.pop(); if (dp[now] < d)continue; if (now!=n&&dp[(now + 1) % n] > d + a) { dp[(now + 1) % n] = d + a; pq.push({ d + a,now + 1 }); } if (dp[kai[now]] > d + c) { dp[kai[now]] = d + c; pq.push({ dp[kai[now]],kai[now] }); } if (now >= ku && dp[n] > d + c) { dp[n] = d + c; pq.push({ dp[n],n }); } if (now != n) { ll p = now, cost = b, pu = 0; while (cost <= border) { if (dp[p] > dp[now] + cost) { dp[p] = dp[now] + cost; pq.push({ dp[p],p }); } if (pu&&dp[n] > d + cost) { dp[n] = d + cost; pq.push({ dp[n],n }); } p *= now; if (p >= n) pu = 1; p %= n; cost *= b; } } } cout << min(dp[0], dp[n] + c); return 0; }