#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll

#define REP(i,n) for(int i=0;i<n;++i)
#define ALL(name) name.begin(),name.end()
#define SORT(name) sort(name.begin(), name.end())
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))
#if 0
#  define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#  define DBG(fmt, ...)
#endif

const ll LLINF = (1LL<<62);
const int INF = (1LL<<30);
const double DINF = std::numeric_limits<double>::infinity();
#define MAX_N 100010

#define SUBMIT

ll M;

struct mint {
    ll x;
    mint(ll x = 0) : x(x % M) {}
    mint& operator += (const mint a) {
        if ( (x += a.x) >= M) { x -= M; }
        return *this;
    }
    mint& operator -= (const mint a) {
        if ( (x += M - a.x) >= M) { x -= M; }
        return *this;
    }
    mint& operator *= (const mint a) {
        (x *= a.x) %= M;
        return *this;
    }
    mint operator + (const mint a) const {
        mint res(*this);
        return res += a;
    }
    mint operator - (const mint a) const {
        mint res(*this);
        return res -= a;
    }
    mint operator * (const mint a) const {
        mint res(*this);
        return res *= a;
    }
};

ll L, A, B;

vector<mint> first_term;  // 桁数 i のものの等差数列の初項
vector<ll> cnt;         // 桁数 i のものが等差数列に登場する数

vector<ll> pow_ten;

template <typename T> inline T power(T x, uint64_t n, T e = 1) { T r = e; while (n > 0) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; }

// 10^n を返す
static inline ll Pow(ll n) { return pow_ten[n]; }
// 数字 n の桁数を返す
static inline ll DigitCnt(ll n) {
    string s = to_string(n);
    return s.length();
}

// 桁数が k のときの初項 x が、元の等差数列でいうと何番目にあたるかを求める(基数は 0)
// 桁数が A より少ないもしくは S(L-1) より大きい場合は -1 が返る
ll GetFirstIndex(ll k) {
    ll ab = A + B;
    // 掛け算の場合…割り算 if を使って判定できる
    if(LLINF / ab > (L - 1)) {
        // OK
        if(k < DigitCnt(A)) { return -1; }
        else if(k == DigitCnt(A)) { return 0; }
        else if(k > A + B * (L-1)) { return -1; }
    } else {
        // overflow
        if(k < DigitCnt(A)) { return -1; }
        else if(k == DigitCnt(A)) { return 0; }
    }

    // Si = A + B * i なので、 i < (10^(k-1) - A) / B のときの i が、
    // k-1 桁のときの最大の i, なのでその i+1 が答え
    ll i = (Pow(k-1) - A) / B;
    if(i <= 0) { i = 1; }
    else if((Pow(k-1) - A) % B != 0) { i++; }

    if(L <= i) { return -1; }

    return i;
}

// 桁数が k のときの初項 x を求める
// 桁数が A より少ないもしくは S(L-1) より大きい場合は -1 が返る
mint GetFirstTerm(ll k) {
    ll i = GetFirstIndex(k);
    if(i < 0) { return -1; }
    return mint(A) + mint(B) * mint(i);
}

// 桁数が k のものが、元の等差数列でいくつ出てくるかを求める
ll GetCnt(ll k) {
    if(GetFirstIndex(k) < 0) { return 0; }
    ll ub = GetFirstIndex(k+1);
    if(ub == -1) { ub = L; }
    return ub - GetFirstIndex(k);
}

// 初項 a, 公比 b の等比数列の第 n 項(1-indexed)までの和を求めます
// mod は素数でなくともいけます
mint GeoProSum(mint a, mint b, uint64_t n) {
    // 第 1 項までの和から初めて、第 n 項になるまで遷移を繰り返す
    if (n == 1) { return a; }
    if(n % 2 == 0) {
        n /= 2;
        return GeoProSum(a, b, n) * (power(b, n) + 1);
    }
    else {
        n--;
        return GeoProSum(a, b, n) + power(b, n);
    }
}

// Tn: 10^k % M
mint AriGeoProSum(ll k, mint Tn, uint64_t n) {
    if(n == 1) { return 0; }
    if(n % 2 == 0) {
        n /= 2;
        return AriGeoProSum(k, Tn, n) * (power(Tn, n) + 1) + mint(n) * GeoProSum(1, Tn, n);
    }
    else {
        n--;
        return AriGeoProSum(k, Tn, n) + GeoProSum(1, Tn, n);
    }
}

signed main() {
    cin.tie(0); cout.tie(0);
    ios::sync_with_stdio(false);

    pow_ten.resize(20);
    pow_ten[0] = 1;
    for(int i = 1; i < 20; ++i) { pow_ten[i] = pow_ten[i-1] * 10; }

#ifdef SUBMIT
    cin >> L >> A >> B >> M;

    cnt.resize(20);
    first_term.resize(20);

    // 各桁の初項と要素数を求める
    DBG("1\n");
    for(int k = 1; k <= 18; ++k) {
        cnt[k] = GetCnt(k);
        first_term[k] = GetFirstTerm(k);
    }

    DBG("2\n");
    mint ans = 0;
    for(int k = 1; k <= 18; ++k) {
        DBG("k: %lld\n", k);

        mint Tn = power(mint(10), k);

        mint tmp_x = first_term[k];
        if(cnt[k] == 0) { continue; }
        DBG("  cnt:           %lld\n", cnt[k]);
        DBG("  first_term[k]: %lld\n", first_term[k].x);
        // 初項 1 , 公比 10^k 等比数列の第 N 項(1-indexed)までの和
        //tmp_x *= GeoProSum(1, Pow(k), cnt[k]);
        tmp_x *= GeoProSum(1, Tn, cnt[k]);
        DBG("  GeoProSum:     %lld\n", GeoProSum(1, Pow(k), cnt[k]).x);
        //DBG("  tmp_x: %lld\n", tmp_x.x);

        // 初項 0, 公差 1 の等差数列と、初項 (10^k)^N-1 公比(10^k)-1 の積の第 N 項(1-indexed) までの和
        mint tmp_y = B;
        tmp_y *= AriGeoProSum(k, Tn, cnt[k]);

        DBG("  AriGeoProSum:  %lld\n", AriGeoProSum(k, Tn, cnt[k]));
        //DBG("  tmp_y: %lld\n", tmp_y.x);

        tmp_x += tmp_y;

        if(k > 1) {
            mint p = power(Tn, cnt[k]);
            //DBG("  p: %lld\n", p.x);
            ans *= p;
        }

        ans += tmp_x;

        DBG("  ans:         %lld\n", ans.x);
    }

    printf("%lld\n", ans.x);
#else
    ll cand = GeoProSum(2, 3, 8, 1000000007);
    ll ans =  GeoProSum(2, 3, 8, 1000000007);
    printf("%lld %lld\n", cand, ans);
#endif

    return 0;
}


Measured memory_bytes: 256