#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using ull = long long;
constexpr int MAXDC = 19;
ll mod; // to be scanf'ed

ll modexp(ll b, ull e) {
	return (e == 0 ? 1 : (e % 2 == 1 ? b : 1) * modexp(b * b % mod, e/2) % mod);
}

int digCount(ll x) {
	if (x <= 9) return 1;
	else return 1 + digCount(x / 10);
}

// MIND = min index with needed digits
ll findMIND(ll a, ll b, int ndc, ll maxFind) {
	if (digCount(a + b * (maxFind - 1)) < ndc) return -1;
	else {
		ll lo = 0;
		ll hi = maxFind - 1;
		while (lo < hi) {
			ll mid = (lo + hi) / 2;
			if (digCount(a + mid * b) >= ndc) hi = mid;
			else lo = mid + 1;
		}
		if (digCount(a + lo * b) == ndc) return lo;
		else return -1;
	}
}

// computes 1 + r + r2 + ... + r^(ct - 1) following the modulo
ll geomSum(ll r, ll ct) {
	if (ct == 1) return 1;
	else if (ct % 2 == 1) return (1 + r * geomSum(r, ct-1) % mod) % mod;
	else {
		// 1 + r + r2 + ... + r^(ct/2 - 1)
		// and r^(ct/2) + ... + r^(ct - 1) = r^(ct/2) * (1 + r + r2 + ... + r^(ct/2 - 1))
		return (modexp(r, ct/2) + 1) * geomSum(r, ct/2) % mod;
	}
}
/*
// computes
// s + (s - dec) * base + (s - 2dec) * base^2 + ... + (s - tc*dec) * base^(tc-1)
if tc = 0,
this is just s

the weights look like

arithGeoSum(9, 4, 2, base)
********* i = 0 => the larger 
******* i = 1 
***** i = 2 => the smaller arith geo starts at this term
*** i = 3
the result is 9 + 7b + 5b^2 + 3b^3
i split this as 5 + 3b + (4 + 4b) + b^2(5 + 3b)

we have to compute the a offset and the g offset
the a offset is the
****
****
so it has a width of tc/2 * dec, so it's all
tc/2 * dec * (1 + base + ... + base^(tc/2 - 1))

the g offset is basically that the smaller AG appears multiplied by base^(tc/2)

*/
ll arithGeoSum(ll s, ll tc, ll dec, ll base) {
	ll ans;
	if (tc == 1) ans = s;
	else if (tc % 2 == 1) {
		ll lastTerm = (s % mod - ((tc - 1) % mod) * (dec % mod) % mod) % mod * modexp(base, tc - 1) % mod;
		ans = (arithGeoSum(s, tc - 1, dec, base) + lastTerm) % mod;
	} else {
		// consider (s - tc/2 * dec) * base^(tc/2 + 1)
		ll smallerAG = arithGeoSum(s - tc/2 * dec, tc/2, dec, base);
		ll arithOffset = (tc/2 * dec % mod * geomSum(base, tc/2)) % mod;
		ans = (arithOffset + (modexp(base, tc/2) + 1) * smallerAG) % mod;
	}
	// printf("ags %lld %lld %lld %lld = %lld\n", s, tc, dec, base, ans % mod);
	return ans % mod;
}

signed main() {
	ll mf, a, b; scanf("%lld %lld %lld %lld", &mf, &a, &b, &mod);
	vector<pair<ll, int>> newDCStart; // (index, dc)
	for (int i = 1; i < MAXDC; ++i) {
		ll dspos = findMIND(a, b, i, mf);
		if (dspos != -1) {
			newDCStart.emplace_back(dspos, i);
		}
	}
	vector<pair<ll, ll>> dcranges(MAXDC, {-1, -1});
	for (int i = 0; i < newDCStart.size(); ++i) {
		if (i + 1 == newDCStart.size()) // this is the last one
			dcranges[newDCStart[i].second] = {newDCStart[i].first, mf - 1};
		else {
			dcranges[newDCStart[i].second] = {newDCStart[i].first, newDCStart[i+1].first - 1};
		}
	}
	// for (int i = 1; i < MAXDC; ++i) {
	// 	printf("%d %lld %lld\n", i, dcranges[i].first, dcranges[i].second);
	// }
	vector<ll> offsetMul(MAXDC);
	ll curOffset = 1;
	for (ll i = MAXDC - 1; i >= 1; --i) {
		if (dcranges[i].first != -1) {
			offsetMul[i] = curOffset;
			curOffset = (curOffset * modexp(modexp(10, dcranges[i].second - dcranges[i].first + 1), i) % mod);
		}
	}
	// for (int i = 1; i < MAXDC; ++i) {
	// 	printf("%lld\n", rowStartsAt[i]);
	// }
	ll ans = 0;
	for (int i = 1; i < MAXDC; ++i) {
		if (dcranges[i].first != -1) {
			ll rstart = a + dcranges[i].second * b;
			// the dec is b, the base is 10, the tc is the sequence length
			ll crcontrib = arithGeoSum(rstart, dcranges[i].second - dcranges[i].first + 1, b, modexp(10, i));
			// printf("%d has crcontrib %lld\n", i, crcontrib);
			ans = (ans + crcontrib * offsetMul[i] % mod) % mod;
		}
	}
	printf("%lld\n", (ans + mod) % mod);
	return 0;
}

Measured memory_bytes: 256