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# (.NET Core 3.1.201) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Numerics;
using System.Threading;
using System.Runtime.CompilerServices;
using static System.Math;
using static System.Array;
using static AtCoder.Sc_out;
using static AtCoder.Tool;
using static AtCoder.ModInt;
namespace AtCoder
{
    class AC
    {
        const int MOD = 1000000007;
        //const int MOD = 998244353;

        const int INF = int.MaxValue / 2;
        const long SINF = long.MaxValue / 2;
        const double EPS = 1e-8;
        static readonly int[] dI = { 0, 1, 0, -1, 1, -1, -1, 1 };
        static readonly int[] dJ = { 1, 0, -1, 0, 1, 1, -1, -1 };
        //static List<List<int>> G = new List<List<int>>();
        //static List<List<Edge>> G = new List<List<Edge>>();
        //static List<Edge> E = new List<Edge>();
        static void Main(string[] args)
        {
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }; Console.SetOut(sw);

            var th = new Thread(Run, 1 << 26);
            th.Start();
            th.Join();

            //Run();
            Console.Out.Flush();
        }
        static void Run()
        {
            int Testcase = 1;
            for (var _ = 0; _ < Testcase; _++) Solve();
        }
        static void Solve()
        {
            long L, A, B, M;
            Cin.Input(out L, out A, out B, out M);
            long s = A;
            int k = 0;
            long idx = 0;
            long nxt = 1;


            long ss = A;
            while (ss > 0) { ss /= 10;k++;nxt *= 10; }
            long ans = 0;
            int keta(long x) => x == 0 ? 0 : keta(x / 10) + 1;
            long modpow(long a, long b) => b == 0 ? 1 : (b % 2 == 0 ? modpow((a * a) % M, b >> 1) : (a * modpow(a, b - 1)) % M);
            while (idx < L)
            {
                long n = (nxt - 1 - s) / B;
                if (k == 18 || idx + n > L - 1) n = L - 1 - idx;
                long s0 = s % M;
                long sn = (s + (n % M) * (B % M)) % M;
                long pw = modpow(10, k);
                long inv = (inverse(pw - 1 + M, M) + M) % M;
                long S = (s0 * modpow(pw, n + 1) % M - sn + M) % M + ((pw * (B % M)) % M * (modpow(pw, n) - 1 + M) % M) * inv % M;
                S *= inv;S %= M;
                ans *= modpow(pw, n+1);ans %= M;
                //OutL(modpow(pw, n));

                ans += S;ans %= M;
                //OutL($"{s0}~{sn},n={n},k={k},ans={ans}");
                idx += n;
                if (idx == L - 1) break;
                idx++;
                s = (s + n * B + B);
                k = keta(s);
                nxt = LPow(10, k);
            }
            OutL(ans);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static long inverse(long x, long mod)
        {
            long b = mod, r = 1, u = 0, t = 0, x2 = x;
            while (b > 0)
            {
                var q = x2 / b;
                t = u;
                u = r - q * u;
                r = t;
                t = b;
                b = x2 - q * b;
                x2 = t;
            }
            return (long)(r < 0 ? r + mod : r);
        }
        public struct Edge
        {
            public int from;

            public int to;
            public long dist;

            public Edge(int t, long c)
            {
                from = -1;
                to = t;
                dist = c;
            }
            public Edge(int f, int t, long c)
            {
                from = f;
                to = t;
                dist = c;
            }
        }
    }
    struct ModInt
    {
        public long value;
        private const int MOD = 1000000007;
        //private const int MOD = 998244353;
        public ModInt(long value) { this.value = value; }
        public static implicit operator ModInt(long a)
        {
            var ret = a % MOD;
            return new ModInt(ret < 0 ? (ret + MOD) : ret);
        }
        public static ModInt operator +(ModInt a, ModInt b) => (a.value + b.value);
        public static ModInt operator -(ModInt a, ModInt b) => (a.value - b.value);
        public static ModInt operator *(ModInt a, ModInt b) => (a.value * b.value);
        public static ModInt operator /(ModInt a, ModInt b) => a * Modpow(b, MOD - 2);
        public static ModInt operator <<(ModInt a, int n) => (a.value << n);
        public static ModInt operator >>(ModInt a, int n) => (a.value >> n);
        public static ModInt operator ++(ModInt a) => a.value + 1;
        public static ModInt operator --(ModInt a) => a.value - 1;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt Modpow(ModInt a, long n)
        {
            var k = a;
            ModInt ret = 1;
            while (n > 0)
            {
                if ((n & 1) != 0) ret *= k;
                k *= k;
                n >>= 1;
            }
            return ret;
        }
        private static readonly List<long> Factorials = new List<long>() { 1 };
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt Fac(long n)
        {
            for (var i = Factorials.Count(); i <= n; i++)
            {
                Factorials.Add((Factorials[i - 1] * i) % MOD);
            }
            return Factorials[(int)n];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ModInt nCr(long n, long r)
        {
            return n < r ? 0 : Fac(n) / (Fac(r) * Fac(n - r));
        }
        public static explicit operator int(ModInt a) => (int)a.value;
    }
    static class Cin
    {
        public static string[] ReadSplit => Console.ReadLine().Split();
        public static int[] ReadSplitInt => ConvertAll(Console.ReadLine().Split(), int.Parse);
        public static long[] ReadSplitLong => ConvertAll(Console.ReadLine().Split(), long.Parse);
        public static double[] ReadSplit_Double => ConvertAll(Console.ReadLine().Split(), double.Parse);
        public static string Str => Console.ReadLine();
        public static int Int => int.Parse(Console.ReadLine());
        public static long Long => long.Parse(Console.ReadLine());
        public static double Double => double.Parse(Console.ReadLine());
        public static T Conv<T>(string input)
        {
            if (typeof(T).Equals(typeof(ModInt)))
            {
                return (T)(dynamic)(long.Parse(input));
            }
            return (T)Convert.ChangeType(input, typeof(T));
        }
        public static void Input<T>(out T a) => a = Conv<T>(Console.ReadLine());
        public static void Input<T, U>(out T a, out U b)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); }
        public static void Input<T, U, V>(out T a, out U b, out V c)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); }
        public static void Input<T, U, V, W>(out T a, out U b, out V c, out W d)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); d = Conv<W>(q[3]); }
        public static void Input<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e)
        { var q = ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]); d = Conv<W>(q[3]); e = Conv<X>(q[4]); }
    }
    static class Sc_out
    {
        public static void OutL(object s) => Console.WriteLine(s);
        public static void Out_Sep<T>(IEnumerable<T> s) => Console.WriteLine(string.Join(" ", s));
        public static void Out_Sep<T>(IEnumerable<T> s, string sep) => Console.WriteLine(string.Join($"{sep}", s));
        public static void Out_Sep(params object[] s) => Console.WriteLine(string.Join(" ", s));
        public static void Out_One(object s) => Console.Write($"{s} ");
        public static void Out_One(object s, string sep) => Console.Write($"{s}{sep}");
        public static void Endl() => Console.WriteLine();
    }
    public static class Tool
    {
        static public void Initialize<T>(ref T[] array, T initialvalue)
        {
            array = ConvertAll(array, x => initialvalue);
        }
        static public void Swap<T>(ref T a, ref T b)
        {
            T keep = a;
            a = b;
            b = keep;
        }
        static public void Display<T>(T[,] array2d, int n, int m)
        {
            for (var i = 0; i < n; i++)
            {
                for (var j = 0; j < m; j++)
                {
                    Console.Write($"{array2d[i, j]} ");
                }
                Console.WriteLine();
            }
        }
        static public long Gcd(long a, long b)
        {
            if (a == 0 || b == 0) return Max(a, b);
            return a % b == 0 ? b : Gcd(b, a % b);
        }
        static public long LPow(int a, int b) => (long)Pow(a, b);
        static public bool Bit(long x, int dig) => ((1L << dig) & x) != 0;
        static public int Sig(long a) => a == 0 ? 0 : (int)(a / Abs(a));
    }
}