Problem:
Score : 600 points

Problem Statement

There is an arithmetic progression with L terms: s_0, s_1, s_2, ... , s_{L-1}.

The initial term is A, and the common difference is B. That is, s_i = A + B \times i holds.

Consider the integer obtained by concatenating the terms written in base ten without leading zeros. For example, the sequence 3, 7, 11, 15, 19 would be concatenated into 37111519. What is the remainder when that integer is divided by M?

Constraints

All values in input are integers.

1 \leq L, A, B < 10^{18}

2 \leq M \leq 10^9

All terms in the arithmetic progression are less than 10^{18}.

Input

Input is given from Standard Input in the following format:

L A B M

Output

Print the remainder when the integer obtained by concatenating the terms is divided by M.

Sample Input 1

5 3 4 10007

Sample Output 1

5563

Our arithmetic progression is 3, 7, 11, 15, 19, so the answer is 37111519 mod 10007, that is, 5563.

Sample Input 2

4 8 1 1000000

Sample Output 2

891011

Sample Input 3

107 10000000000007 1000000000000007 998244353

Sample Output 3

39122908

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

//include
//------------------------------------------
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>

#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>

#include <stdexcept>

using namespace std;

//conversion
//------------------------------------------
inline int toint(string s) { int v; istringstream sin(s); sin >> v; return v; }
template<class t> inline string tostring(t x) { ostringstream sout; sout << x; return sout.str(); }

//debug
#define dump(x)  cerr << #x << " = " << (x) << endl
#define debug(x) cerr << #x << " = " << (x) << " (l" << __line__ << ")" << " " << __file__ << endl

// type alias
using ll = long long;
using ull = unsigned long long;

inline bool isPower2(ull a)
{
	if (a == 0)
	{
		return false;
	}
	return !(a & (a - 1));
}

inline ll getMaxEffectiveBit(ull a)
{
	ll index = -1;
	for (; a != 0; a >>= 1)
	{
		++index;
	}
	return index;
}

inline ll getSpecifiedBit(ull a, unsigned bit)
{
	return (a & (1LL << bit)) >> bit;
}

// computational complexity: o(log(max(a, b))) 
inline ull getGcd(ull a, ull b)
{
	if (b == 0)
	{
		return a;
	}
	return getGcd(b, a % b);
}

template<class Integer>
inline Integer getPower(Integer base, unsigned exponential)
{
	Integer result = 1;
	while (exponential >= 1)
	{
		if (exponential & 1)
		{
			result = result * base;
		}
		base = base * base;
		exponential >>= 1;
	}

	return result;
}



template <class Integer>
class ResidueInteger
{
private:
	Integer mod_;
	Integer n_;
	//static Integer global_mod_;

	// computational complexity: o(log(max(a, b))) 
	static inline pair<Integer, Integer> getBezoutsIdentitySolution(Integer a, Integer b)
	{
		if (b == 0)
		{
			return { 1, 0 };
		}
		auto sol = getBezoutsIdentitySolution(b, a % b);
		return { sol.second, sol.first - (a / b) * sol.second };
	}

public:
	static Integer global_mod_;
	Integer getModValue(const Integer& n) const
	{
		return (n % mod_ + mod_) % mod_;
	}

	// computational complexity: o(log(max(n, mod))) 
	inline Integer getModInverse(const Integer& n) const
	{
		auto sol = getBezoutsIdentitySolution(n, mod_);
		if (n * sol.first + mod_ * sol.second != 1)
		{
			stringstream ss;
			ss << "There exists no inverse of " << n << " in mod " << mod_ << ".";
			throw invalid_argument(ss.str());
		}
		return getModValue(sol.first);
	}

	ResidueInteger() : mod_(global_mod_), n_(getModValue(0)) {}
	ResidueInteger(Integer n) : mod_(global_mod_), n_(getModValue(n)) {}
	ResidueInteger(Integer n, Integer mod) : mod_(mod), n_(getModValue(n)) {}

	inline ResidueInteger operator+(const ResidueInteger& rhs) const
	{
		if (this->mod_ != rhs.mod_)
		{
			throw invalid_argument("The mods of both operands should be equal.");
		}
		return { this->n_ + rhs.n_, this->mod_ };
	}
	inline ResidueInteger operator+(const Integer& rhs) const
	{
		return { this->n_ + getModValue(rhs), this->mod_ };
	}
	friend inline ResidueInteger operator+(const Integer& lhs, const ResidueInteger& rhs)
	{
		return { rhs.getModValue(lhs) + rhs.n_, rhs.mod_ };
	}
	inline ResidueInteger& operator+=(const ResidueInteger& rhs)
	{
		if (this->mod_ != rhs.mod_)
		{
			throw invalid_argument("The mods of both operands should be equal.");
		}
		this->n_ = getModValue(this->n_ + rhs.n_);
		return *this;
	}
	inline ResidueInteger& operator+=(const Integer& rhs)
	{
		this->n_ = getModValue(this->n_ + getModValue(rhs));
		return *this;
	}

	inline ResidueInteger operator-(const ResidueInteger& rhs) const
	{
		if (this->mod_ != rhs.mod_)
		{
			throw invalid_argument("The mods of both operands should be equal.");
		}
		return { this->n_ - rhs.n_, this->mod_ };
	}
	inline ResidueInteger operator-(const Integer& rhs) const
	{
		return { this->n_ - getModValue(rhs), this->mod_ };
	}
	friend inline ResidueInteger operator-(const Integer& lhs, const ResidueInteger& rhs)
	{
		return { rhs.getModValue(lhs) - rhs.n_, rhs.mod_ };
	}
	inline ResidueInteger& operator-=(const ResidueInteger& rhs)
	{
		if (this->mod_ != rhs.mod_)
		{
			throw invalid_argument("The mods of both operands should be equal.");
		}
		this->n_ = getModValue(this->n_ - rhs.n_);
		return *this;
	}
	inline ResidueInteger& operator-=(const Integer& rhs)
	{
		this->n_ = getModValue(this->n_ - getModValue(rhs));
		return *this;
	}

	inline ResidueInteger operator*(const ResidueInteger& rhs) const
	{
		if (this->mod_ != rhs.mod_)
		{
			throw invalid_argument("The mods of both operands should be equal.");
		}
		return { this->n_ * rhs.n_, this->mod_ };
	}
	inline ResidueInteger operator*(const Integer& rhs) const
	{
		return { this->n_ * getModValue(rhs), this->mod_ };
	}
	friend inline ResidueInteger operator*(const Integer& lhs, const ResidueInteger& rhs)
	{
		return { rhs.getModValue(lhs) * rhs.n_, rhs.mod_ };
	}
	inline ResidueInteger& operator*=(const ResidueInteger& rhs)
	{
		if (this->mod_ != rhs.mod_)
		{
			throw invalid_argument("The mods of both operands should be equal.");
		}
		this->n_ = getModValue(this->n_ * rhs.n_);
		return *this;
	}
	inline ResidueInteger& operator*=(const Integer& rhs)
	{
		this->n_ = getModValue(this->n_ * getModValue(rhs));
		return *this;
	}

	inline ResidueInteger operator/(const ResidueInteger& rhs) const
	{
		if (this->mod_ != rhs.mod_)
		{
			throw invalid_argument("The mods of both operands should be equal.");
		}
		return { this->n_ * getModInverse(rhs.n_), this->mod_ };
	}
	inline ResidueInteger operator/(const Integer& rhs) const
	{
		return { this->n_ * getModInverse(getModValue(rhs)), this->mod_ };
	}
	friend inline ResidueInteger operator/(const Integer& lhs, const ResidueInteger& rhs)
	{
		return { rhs.getModValue(lhs) * rhs.getModInverse(rhs.n_), rhs.mod_ };
	}
	inline ResidueInteger& operator/=(const ResidueInteger& rhs)
	{
		if (this->mod_ != rhs.mod_)
		{
			throw invalid_argument("The mods of both operands should be equal.");
		}
		this->n_ = getModValue(this->n_ * getModInverse(rhs.n_));
		return *this;
	}
	inline ResidueInteger& operator/=(const Integer& rhs)
	{
		this->n_ = getModValue(this->n_ * getModInverse(getModValue(rhs)));
		return *this;
	}

	inline bool operator==(const ResidueInteger& rhs) const
	{
		return (this->n_ == rhs.n_) && (this->mod_ == rhs.mod_);
	}
	inline bool operator==(const Integer& rhs) const
	{
		return this->n_ == getModValue(rhs);
	}
	friend bool operator==(const Integer& lhs, const ResidueInteger& rhs)
	{
		return rhs.getModValue(lhs) == rhs.n_;
	}

	Integer getN() const { return n_; }

	friend std::ostream& operator<<(std::ostream& lhs, const ResidueInteger& rhs)
	{
		return lhs << rhs.n_;
	}

	friend std::istream& operator>>(std::istream& lhs, ResidueInteger& rhs)
	{
		lhs >> rhs.n_;
		return lhs;
	}
};
using rll = ResidueInteger<ll>;
ll mod = 1000000007ll;
template<> ll rll::global_mod_ = mod;



template <class Integer>
class Matrix
{
private:
	ull rowCount_;
	ull colCount_;
	vector<Integer> values_;
public:
	Matrix(ull rowCount = 0ULL, ull colCount = 0ULL) :
		rowCount_(rowCount), colCount_(colCount),
		values_(rowCount_ * colCount_) { }

	ull getRowCount() const
	{
		return rowCount_;
	}

	ull getColCount() const
	{
		return colCount_;
	}

	Integer& operator()(ull rowIndex, ull colIndex)
	{
		return values_[rowIndex * colCount_ + colIndex];
	}

	const Integer& operator()(ull rowIndex, ull colIndex) const
	{
		return values_[rowIndex * colCount_ + colIndex];
	}

	inline Matrix operator*(const Matrix& rhs) const
	{
		if (colCount_ != rhs.rowCount_)
		{
			throw invalid_argument("The column size of the left matrix should be equal to the row size of the right matrix.");
		}
		Matrix res(this->rowCount_, rhs.colCount_);
		for (ll i = 0; i < rowCount_; ++i)
		{
			for (ll j = 0; j < rhs.colCount_; ++j)
			{
				for (ll k = 0; k < colCount_; ++k)
				{
					res(i, j) += (*this)(i, k) * rhs(k, j);
				}
			}
		}

		return res;
	}

	friend std::ostream& operator<<(std::ostream& lhs, const Matrix& rhs)
	{
		for (ll i = 0; i < rhs.rowCount_; ++i)
		{
			if (i == 0)
			{
				lhs << "[";
			}
			else
			{
				lhs << " ";
			}

			lhs << "[";
			for (ll j = 0; j < rhs.colCount_; ++j)
			{
				lhs << rhs.values_[i * rhs.colCount_ + j];
				if (j + 1 < rhs.colCount_)
				{
					lhs << ", ";
				}
			}

			if (i + 1 < rhs.rowCount_)
			{
				lhs << "]," << endl;
			}
			else
			{
				lhs << "]]";
			}
		}
		return lhs;
	}
};

template<class Integer>
inline Matrix<Integer> getPower(Matrix<Integer> base, unsigned exponential)
{
	if (base.getRowCount() != base.getColCount())
	{
		throw invalid_argument("The base matrix should be a square matrix.");
	}

	ull size = base.getRowCount();

	Matrix<Integer> result(size, size);
	for (ull i = 0; i < size; ++i)
	{
		result(i, i) = 1;
	}
	while (exponential >= 1)
	{
		if (exponential & 1)
		{
			result = result * base;
		}
		base = base * base;
		exponential >>= 1;
	}

	return result;
}


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


	ll L, A, B, M;
	cin >> L >> A >> B >> M;

	rll::global_mod_ = M;
	using mat = Matrix<rll>;

	rll res = 0;
	ll prev_index = 0, curr_index;
	ll base = 1;
	for (ll i = 1; prev_index < L && i <= 20; prev_index = curr_index, ++i)
	{
		base *= 10;
		curr_index = min(max(ll(ceil((base - A + B - 1) / B)), 0LL), L);
		if (curr_index <= prev_index)
		{
			continue;
		}

		mat recurrenceMatrix(4, 4);
		recurrenceMatrix(0, 0) = rll(base), recurrenceMatrix(0, 1) = 0, recurrenceMatrix(0, 2) = 0, recurrenceMatrix(0, 3) = 0,
		recurrenceMatrix(1, 0) = rll(base), recurrenceMatrix(1, 1) = rll(base), recurrenceMatrix(1, 2) = 0, recurrenceMatrix(1, 3) = 0,
		recurrenceMatrix(2, 0) = 1, recurrenceMatrix(2, 1) = 0, recurrenceMatrix(2, 2) = 1, recurrenceMatrix(2, 3) = 0,
		recurrenceMatrix(3, 0) = 0, recurrenceMatrix(3, 1) = 1, recurrenceMatrix(3, 2) = 0, recurrenceMatrix(3, 3) = 1;

		mat initialMatrix(4, 1);
		initialMatrix(0, 0) = 1, initialMatrix(1, 0) = 0, initialMatrix(2, 0) = 0, initialMatrix(3, 0) = 0;

		ll sequenceLength = curr_index - prev_index;

		mat resultingMatrix = getPower(recurrenceMatrix, sequenceLength) * initialMatrix;
		rll sumR = resultingMatrix(2, 0), sumNR = resultingMatrix(3, 0);
		
		res *= getPower(rll(10), i * sequenceLength);
		res += (rll(A) + rll(B) * (curr_index - 1)) * sumR - rll(B) * sumNR;
	}

	cout << res << endl;

	return 0;
}