#if 1
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <climits>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
#include <functional>
#include <set>
#include <map>
#include <numeric>
#include <cassert>
#include <iomanip>
#define _SCL_SECURE_NO_WARNINGS
#include "boost/multiprecision/cpp_int.hpp"

#pragma warning (disable:4244)



using namespace std;
#define int boost::multiprecision::int128_t
#define uint unsigned long long
constexpr long long MOD = 1000000007LL;
//constexpr int MOD = 998244353;
constexpr long long INF = 1145141919810893LL;

//
#if 1
struct Edge {
	int next;
	int w = 1;
};
template<class T>
struct Vertex {
	std::vector<Edge>edges;
	T val = {};
};
template<class T>
struct Graph {
	std::vector<Vertex<T>> vertex;
public:
	Graph(size_t n = 0) :vertex(n) {
	}
	void setArray(int u, int v, int w = 1) {
		vertex[u].edges.push_back(Edge{ v ,w });
	}
	void setConnect(int u, int v, int w = 1) {
		setArray(u, v, w);
		setArray(v, u, w);
	}
	T& val(int u) {
		return vertex[u].val;
	}
	void dfsImpl(int pos, int prev, std::function<void(int now, int next, int w)> func) {
		for (auto& e : vertex[pos].edges) {
			if (e.next == prev) continue;
			func(pos, e.next, e.w);
			dfsImpl(e.next, pos, func);
		}
	}
	void dfs(int pos, std::function<void(int now, int next, int w)> func) {
		dfsImpl(pos, -1, func);
	}
	//graph.dfs(0, [](Vertex<int>& now, Vertex<int>& next, int w) {});
	pair<int, int> radiusImpl(int pos) {
		int farestID = -1;
		int far = -1;
		val(pos) = 0;
		dfs(pos, [&](int now, int next, int w) {
			val(next) = 1 + val(now);
			if (val(next) > far) {
				far = val(next);
				farestID = next;
			}
			});
		return { farestID, far };
	}
	int radius() {
		if (vertex.size() <= 1)return 0;
		auto res = radiusImpl(0);
		res = radiusImpl(res.first);
		return res.second;
	}
};
#endif

//////////////////////////////////
int gcd(int x, int y) { return y ? gcd(y, x % y) : x; }

std::vector<int> divisor(int n) {
	std::vector<int> ret;
	for (int i = 1; i * i <= n; ++i) {
		if (n % i == 0) {
			ret.push_back(i);
			if (i * i != n) {
				ret.push_back(n / i);
			}
		}
	}
	return ret;
}

bool isPrime(int n) {
	if (n <= 1)return false;
	if (n == 2)return true;
	if (n % 2 == 0)return false;
	for (int i = 3; i * i <= n; i += 2) {
		if (n % i == 0)return false;
	}
	return true;
}

////////////////////////
#if 0
class Combination {
	std::vector<int>fac, finv, inv;
public:
	Combination(int N) :fac(N + 1), finv(N + 1), inv(N + 1) {
		fac[0] = fac[1] = 1;
		finv[0] = finv[1] = 1;
		inv[1] = 1;
		for (long long i = 2; i < N + 1; i++) {
			fac[i] = fac[i - 1] * i % MOD;
			inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
			finv[i] = finv[i - 1] * inv[i] % MOD;
		}
	}
	int get(int n, int k) {
		if (n < k) return 0;
		if (n < 0 || k < 0) return 0;
		return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
	}
};

#endif
#if 1

int modInv(int a) {
	int b = MOD, u = 1, v = 0;
	while (b) {
		int t = a / b;
		a -= t * b; swap(a, b);
		u -= t * v; swap(u, v);
	}
	u %= MOD;
	if (u < 0) u += MOD;
	return u;
}


void modify(int& n, int mod = MOD) {
	if (n < 0) {
		n %= mod;
		n += mod;
	}
	n %= mod;
}

#endif

//文字列の置き換え(遅い？)
int replace(std::string* str, const std::string& old_, const std::string& new_) {
	std::string& String1 = *str;
	//String1.reserve(str->size() * new_.size() / old_.size() + 1);
	std::string::size_type  Pos(String1.find(old_));
	int result = 0;
	while (Pos != std::string::npos) {
		result++;
		String1.replace(Pos, old_.length(), new_);
		Pos = String1.find(old_, Pos + new_.length());
	}
	return result;
}

//MODで割ったあまりの演算
struct Rational {
	int r;
	Rational(int rr) :r(rr) {
	}
	operator int() {
		return r;
	}
	Rational operator+(const Rational& other)const {
		Rational res(0);
		res.r = r + other.r;
		modify(res.r);
		return res;
	}
	Rational operator-(const Rational& other)const {
		Rational res(0);
		res.r = r - other.r;
		modify(res.r);
		return res;
	}
	Rational operator*(const Rational& other) const {
		Rational res(0);
		res.r = r * other.r;
		modify(res.r);
		return res;
	}
	Rational operator/(const Rational& other)const {
		Rational res(0), res1(0);
		res = *this;
		res1.r = modInv(other.r);
		res = (*this) * res1;
		modify(res.r);
		return res;
	}
	void operator+=(const Rational& other) {
		*this = *this + other;
	}
	void operator-=(const Rational& other) {
		*this = *this - other;
	}
	void operator*=(const Rational& other) {
		*this = *this * other;
	}
	void operator/=(const Rational& other) {
		*this = *this / other;
	}
};

Rational pow(Rational r, int N) {
	if (N == 0)return Rational(1);
	if (N % 2 == 1)return r * pow(r, N - 1);
	Rational tmp = pow(r, N / 2);
	return tmp * tmp;
}
Rational operator"" _r(unsigned long long val) {
	return Rational(val);
}

/////////////////////

#define LOADVEC(type,name,N) std::vector<type>name(N); \
for (int nnn = 0; nnn < N; ++nnn) { \
	cin >> name[nnn]; \
}

#define LOADVEC2(type,name0,name1,N) std::vector<type>name0(N),name1(N); \
for (int nnn = 0; nnn < N; ++nnn) { \
	cin >> name0[nnn];cin >> name1[nnn]; \
}

#define LOADVEC3(type,name0,name1,name2,N) std::vector<type>name0(N),name1(N),name2(N); \
for (int nnn = 0; nnn < N; ++nnn) { \
	cin >> name0[nnn];cin >> name1[nnn];cin >> name2[nnn]; \
}

#define LOAD(type,name) type name; \
cin >> name;

template <class T>
void SORT(T& t) {
	std::sort(t.begin(), t.end());
}


void proc();

signed main() {
	ios::sync_with_stdio(false);
	proc();
	return 0;
}

/*
--------------------------------------------------------
--------------------------------------------------------
---------------    template      ----------------------
--------------------------------------------------------
--------------------------------------------------------
*/

int pow10(int N) {
	int res = 1;
	for (int i = 0; i < N; ++i) {
		res *= 10;
	}
	return res;
}

int tenModM(int L, int M, int base) {
	if (L == 0) {
		return 1;
	}
	if (L % 2 == 1) {
		return (base * tenModM(L - 1, M, base)) % M;
	}
	int tmp = tenModM(L / 2, M, base);
	return (tmp * tmp) % M;
}

//
int oneModM(int L, int M, int base) {

	if (L == 1) {
		return 1;
	}
	if (L % 2 == 1) {
		return (base * oneModM(L - 1, M, base) + 1) % M;
	}
	int tmp = oneModM(L / 2, M, base);
	return (tmp * (1 + tenModM(L / 2, M, base))) % M;
}

int seqModM(int L, int M, int base) {
	if (L == 0) {
		return 0;
	}
	if (L == 1) {
		return 1;
	}
	if (L % 2 == 1) {
		return (base * seqModM(L - 1, M, base) + L) % M;
	}
	int tmp = seqModM(L / 2, M, base);
	return (tmp * (1 + tenModM(L / 2, M, base)) + (L / 2 * oneModM(L / 2, M, base)) % M) % M;
}

int keta(int N) {
	int tmp = 1;
	for (int i = 0;; ++i) {
		if (N < tmp)return i;
		tmp *= 10;
	}
}

int solve(int L, int A, int B, int M, int base) {
	int res = 0;
	modify(A, M);
	modify(B, M);
	res += (A * oneModM(L, M, base)) % M;
	modify(res, M);
	res += (B * seqModM(L - 1, M, base)) % M;
	modify(res, M);
	return res;
}
int solve(int L, int A, int B, int M) {
	int ketaA = keta(A);
	int ketaB = keta(A + B * (L - 1));
	if (ketaA == ketaB)return solve(L, A, B, M, pow10(ketaA) % M);
	int base = pow10(ketaB);
	int id = (base / 10 - A) / B;
	int keta0 = keta(A + B * (id - 1));
	int keta1 = keta(A + B * (id));
	int keta2 = keta(A + B * (id + 1));
	int idd;
	if (keta0 == ketaB) {
		idd = id - 1;
	}
	else if (keta1 == ketaB) {
		idd = id;
	}
	else {
		assert(keta2 == ketaB);
		idd = id + 1;
	}
	int tmp = solve(L - idd, A + idd * B, B, M, base % M);
	int tmp2 = solve(idd, A, B, M);

	tmp2 *= tenModM(ketaB * (L - idd), M, 10);
	modify(tmp2, M);
	return (tmp + tmp2) % M;
}

void proc() {
	LOAD(int, L);
	LOAD(int, A);
	LOAD(int, B);
	LOAD(int, M);
	cout << solve(L, A, B, M) << endl;


}


#endif


Measured memory_bytes: 384