#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <bitset>
#include <array>
#include <vector>
#include <queue>
#include <set>
#include <cmath> // 変数名にy1が使えなくなるかも…。
#include <map>
#include <unordered_map>
#include <unordered_set>

#include <string>

typedef __int128_t int128_t; // VScodeが__int128_tを<error-type>扱いするため、このようにtypedefしてint128_tを使った方が見やすくなる。

int digit(const int128_t n, const int128_t b) {
    // 基数bでの桁数。0は0桁。非常に大きい数を入れても問題ないようにint128_tとする。intやlong longを入れても問題ないはず。
    // 出力しやすいように、戻り値はintにしておく。
    assert(1 < b);
    int ret = 0;
    int128_t tmp = 1;
    while (tmp <= n) {
        ret++;
        tmp *= b;
    }
    return ret;
}

// binary search result
struct BSR {
    bool found; // 条件を満たす範囲が見つかったか。falseの場合、begin,endは意味を持たない。
    long long begin; // [begin, end]で条件が成り立つ。
    long long end;

    BSR(bool found_in, long long begin_in, long long end_in) : found(found_in), begin(begin_in), end(end_in) {}
};

template<class Fn> BSR my_binary_search(long long L, long long R, Fn func) {
    if (func(L) && func(R)) {
        return BSR(true, L, R);
    } else if (!func(L) && !func(R)) {
        return BSR(false, 0, 0);
    } else {
        long long lb = L;
        long long ub = R;
        while (lb + 1 < ub) {
            long long mid = (lb + ub) / 2;
            if (func(L) == func(mid)) {
                lb = mid;
            } else {
                ub = mid;
            }
        }
        if (func(L)) {
            return BSR(true, L, lb);
        } else {
            return BSR(true, ub, R);
        }
    } 
}

int128_t cal_mod(const int128_t n, const int128_t mod) {
    // n % modを計算する。ただしmod <= 0 ならば何もしない。nが負の場合、正にして補正する。
    if (mod <= 0) {
        return n;
    } else if (0 <= n) {
        return n % mod;
    } else {
        int128_t tmp = (-n) / mod + 1;
        return (n + tmp * mod) % mod;
    }
}

int128_t combi(int128_t n, int128_t r) {
    // nCr の計算。rが定数で結果が128bitにおさまる範囲を想定。nとrは明らかに32bit以下だが、念のためのオーバーフロー対策で128bitにキャストしておく。
    assert(0 <= r && r <= n);
    int128_t ret = 1;
    for (int i = 0; i < r; i++) {
        ret = ret * (n - i) / (i + 1);
    }
    return ret;
}

int128_t pow_mod(int128_t x, int128_t n, const int128_t mod) {
    // 累乗の計算。mod <= 0ならば余りの計算は行わない。
    int128_t ret = 1;
    while (n > 0) {
        if (n & 1) { ret = cal_mod(ret * x, mod); }
        x = cal_mod(x * x, mod);
        n = (n >> 1);
    }
    return ret;
}

int128_t dot_product(const std::vector<int128_t>& a, const std::vector<int128_t>& b, const int128_t mod) {
    // mod に正の値を入れると、modの余りを計算する。デフォルト引数でmod = -1とすれば、入力を省ける。
    assert(a.size() == b.size());
    int128_t ret = 0;;
    for (int i = 0; i < a.size(); i++) {
        ret += a[i] * b[i];
    }
    return cal_mod(ret, mod);
}

class Matrix {
    public:
    std::vector<std::vector<int128_t>> M;

    void reset(const int H, const int W) {
        M.resize(H);
        for (int i = 0; i < H; i++) {
            M[i].resize(W, 0);
        }
    }
    Matrix() {}
    Matrix(const int H, const int W) {
        reset(H, W);
    }
    int size_r() const { return M.size(); }
    int size_c() const { assert(0 < size_r()); return M[0].size(); }

    void set_diag(int128_t v) {
        reset(size_r(), size_c());
        for (int i = 0; i < std::min(size_r(), size_c()); i++) {
            M[i][i] = v;
        }
    }
};

std::vector<int128_t> mat_mul_vec(const Matrix& mat, const std::vector<int128_t>& vec, const int128_t mod) {
    // 行列とベクトルの積。除算が不要の場合デフォルトでmod = -1とする。
    assert(mat.size_c() == vec.size());
    std::vector<int128_t> ret;
    ret.resize(mat.size_r());
    for (int i = 0; i < ret.size(); i++) {
        ret[i] = dot_product(mat.M[i], vec, mod);
    }
    return ret;
}

Matrix transpose(const Matrix& mat) {
    Matrix ret = Matrix(mat.size_c(), mat.size_r());
    for (int i = 0; i < ret.size_r(); i++) {
        for (int j = 0; j < ret.size_c(); j++) {
            ret.M[i][j] = mat.M[j][i];
        }
    }
    return ret;
}

Matrix mat_mul(const Matrix& A, const Matrix& B, const int128_t mod) {
    // 行列の積。除算が不要の場合デフォルトでmod = -1とする。
    assert(A.size_c() == B.size_r());
    const Matrix tB = transpose(B);
    Matrix ret = Matrix(A.size_r(), B.size_c());
    for (int i = 0; i < ret.size_r(); i++) {
        for (int j = 0; j < ret.size_c(); j++) {
            ret.M[i][j] = dot_product(A.M[i], tB.M[j], mod);
        }
    }
    return ret;
}

Matrix mat_pow(Matrix A, int128_t n, const int128_t mod) {
    assert(A.size_r() == A.size_c());
    Matrix B = Matrix(A.size_r(), A.size_c());
    B.set_diag(1);

    while (n > 0) {
        if (n & 1) { B = mat_mul(B, A, mod); }
        A = mat_mul(A, A, mod);
        n = (n >> 1);
    }
    return B;
}

int128_t pow_series_sum(const int128_t r, const int k, const int128_t n, const int128_t mod) {
    // (sum m:[0,n-1] m^k * r^m) % mod を求める。
    // modは素数でなくてもよい。mod <= 0 なら除算しない。
    // kは定数想定。k = 0 の時は等比級数の和 = (r^n - 1) / (r - 1) になる。しかし、公式を使うのではなく実際に数値計算をするため、r-1の逆元が不要。
    // 計算量はO(k^3 logn)程度のはず。

    Matrix mat = Matrix(k+2, k+2);
    for (int i = 0; i <= k; i++) {
        for (int j = 0; j <= i; j++) {
            mat.M[i][i-j] = combi(i, j) * pow_mod(-1, j, -1);
        }
    }
    mat.M[k+1][k+1] = r;
    mat.M[k+1][k] = 1;
    std::vector<int128_t> vec;
    vec.resize(k+2);
    for (int i = 0; i <= k; i++) {
        vec[i] = pow_mod(n-1, i, mod);
    }
    vec[k+1] = 0;

    mat = mat_pow(mat, n, mod);
    vec = mat_mul_vec(mat, vec, mod);

    return vec[k+1];
}

int128_t L, A, B, M;

int main(int argc, char **argv) {
    long long input;
    std::cin >> input; L = input;
    std::cin >> input; A = input;
    std::cin >> input; B = input;
    std::cin >> input; M = input;

    int128_t end = L - 1;
    int dig = digit(A + B * end, 10);
    int128_t ret = 0;
    int128_t tmp = 1;

    while (true) {
        BSR bsr = my_binary_search(0, end, 
            [&](const int128_t i) { return digit(A + B * i, 10) == dig; }
        );
        int128_t num = end - bsr.begin + 1;
        ret = ret + ((A + B * end) % M) * pow_series_sum(pow_mod(10, dig, M), 0, num, M) * tmp ; // M が32bitに収まるなら、掛け算3回は無問題のはず。
        ret = cal_mod(ret, M);
        
        ret = ret - (B % M) * pow_series_sum(pow_mod(10, dig, M), 1, num, M) * tmp;
        ret = cal_mod(ret, M);

        if (bsr.begin == 0) {
            break;
        } else {
            tmp = (tmp * pow_mod(10, dig * num, M)) % M;
            end = bsr.begin - 1;
            dig = digit(A + B * end, 10);
        }
    }

    std::cout << (int)ret << std::endl;

    return 0;
}


Measured memory_bytes: 384