Problem:
Score : 500 points

Problem Statement

Takahashi has a string S of length N consisting of digits from 0 through 9.

He loves the prime number P. He wants to know how many non-empty (contiguous) substrings of S - there are N \times (N + 1) / 2 of them - are divisible by P when regarded as integers written in base ten.

Here substrings starting with a 0 also count, and substrings originated from different positions in S are distinguished, even if they are equal as strings or integers.

Compute this count to help Takahashi.

Constraints

1 \leq N \leq 2 \times 10^5

S consists of digits.

|S| = N

2 \leq P \leq 10000

P is a prime number.

Input

Input is given from Standard Input in the following format:

N P
S

Output

Print the number of non-empty (contiguous) substrings of S that are divisible by P when regarded as an integer written in base ten.

Sample Input 1

4 3
3543

Sample Output 1

6

Here S = 3543. There are ten non-empty (contiguous) substrings of S:

3: divisible by 3.

35: not divisible by 3.

354: divisible by 3.

3543: divisible by 3.

5: not divisible by 3.

54: divisible by 3.

543: divisible by 3.

4: not divisible by 3.

43: not divisible by 3.

3: divisible by 3.

Six of these are divisible by 3, so print 6.

Sample Input 2

4 2
2020

Sample Output 2

10

Here S = 2020. There are ten non-empty (contiguous) substrings of S, all of which are divisible by 2, so print 10.

Note that substrings beginning with a 0 also count.

Sample Input 3

20 11
33883322005544116655

Sample Output 3

68

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

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; i < n; ++i)
#define REPR(i, n) for (int i = n - 1; i >= 0; --i)
#define FOR(i, a, b) for (int i = a; i < b; ++i)
#define FORR(i, a, b) for (int i = b - 1; i >= a; --i)
#define SORT(v) sort(v.begin(), v.end())
#define SORTR(v) sort(v.rbegin(), v.rend())
#define REV(v) reverse(v.begin(), v.end())
#define ITER(v) for (auto itr = v.begin(), itr != v.end(); ++itr)
#define LB(v, x) lower_bound(v.begin(), v.end(), x) - v.begin()
#define UB(v, x) upper_bound(v.begin(), v.end(), x) - v.begin()
#define SZ(v) (int)v.size()
using namespace std;
using ll = long long;
using P = pair<int, int>;

int p;
class Zp {
    // const int p = 1000000007;
    ll r;
    void set(ll x) {
        while (x < 0) x += p;
        r = x % p;
    }

public:
    Zp(ll x) { set(x); }
    Zp() { set(0); }

    Zp operator-() const { return Zp(-r); }
    Zp &operator=(ll y) {
        set(y);
        return *this;
    }
    Zp &operator=(const Zp &y) { return *this = y.r; }

    Zp &operator+=(ll y) {
        set(r + y);
        return *this;
    }
    Zp &operator-=(ll y) { return *this += -y; }
    Zp &operator*=(ll y) {
        set(r * y);
        return *this;
    }
    Zp &operator/=(ll y) { return *this *= inv(y); }
    Zp operator+(ll y) const { return Zp(r + y); }
    Zp operator-(ll y) const { return *this + (-y); }
    Zp operator*(ll y) const { return Zp(r * y); }
    Zp operator/(ll y) const { return *this * inv(y); }

    Zp &operator+=(const Zp &y) { return *this += y.r; }
    Zp &operator-=(const Zp &y) { return *this -= y.r; }
    Zp &operator*=(const Zp &y) { return *this *= y.r; }
    Zp &operator/=(const Zp &y) { return *this /= y.r; }
    Zp operator+(const Zp &y) const { return *this + y.r; }
    Zp operator-(const Zp &y) const { return *this - y.r; }
    Zp operator*(const Zp &y) const { return *this * y.r; }
    Zp operator/(const Zp &y) const { return *this / y.r; }

    Zp pow(int n) const {
        if (n == 0) return 1;
        if (n % 2) return *this * pow(n - 1);
        Zp tmp = pow(n / 2);
        return tmp * tmp;
    }
    Zp inv(int x) const { return Zp(x).pow(p - 2); }
    Zp inv() const { return inv(r); }

    ll get() const { return r; }

    friend istream &operator>>(istream &istr, Zp &x) {
        istr >> x.r;
        x.set(x.r);
        return istr;
    }
    friend ostream &operator<<(ostream &ostr, const Zp &x) {
        ostr << x.r;
        return ostr;
    }
};
class Comb {
    vector<Zp> fact, ifact;

public:
    Comb(int N) : fact(N + 1), ifact(N + 1) {
        fact[0] = 1;
        REP(i, N) fact[i + 1] = fact[i] * (i + 1);
        ifact[N] = fact[N].inv();
        REPR(i, N) ifact[i] = ifact[i + 1] * (i + 1);
    }
    Zp operator()(int n, int k) const {
        return fact[n] * ifact[n - k] * ifact[k];
    }
    Zp f(int k) const { return fact[k]; }
    Zp invf(int k) const { return ifact[k]; }
};
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    int N;
    string S;
    cin >> N >> p >> S;
    if (p == 2 || p == 5) {
        ll res = 0;
        REP(i, N) {
            if ((S[i] - '0') % p == 0) { res += i + 1; }
        }
        cout << res << endl;
        return 0;
    }
    vector<Zp> T(N + 1);
    vector<ll> memo(p);
    memo[0]++;
    Zp mul = 1;
    REPR(i, N) {
        T[i] = T[i + 1] + mul * (S[i] - '0');
        memo[T[i].get()]++;
        mul *= 10;
    }
    ll res = 0;
    REP(i, p) { res += memo[i] * (memo[i] - 1) / 2; }
    cout << res << endl;

    return 0;
}