Problem p02757 (C++)

Buggy submission (status: Time Limit Exceeded):
#ifdef DEBUG_IS_VALID
#define DEB 1
#define _LIBCPP_DEBUG 0
#else
#define DEB 0
#define NDEBUG
#endif

#include <bits/stdc++.h>
using namespace std;

#define ALL(g) (g).begin(), (g).end()
#define REP(i, x, n) for (long long i = x; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define RREP(i, x, n) for (long long i = x; i >= n; i--)
#define rrep(i, n) RREP(i, n, 0)
#define pb push_back
#define fi first
#define se second
#pragma GCC optimize("-O3")

using namespace std;

#define DUMPOUT cout
#define dump(...)                                                              \
  if (DEB)                                                                     \
    DUMPOUT << "  " << #__VA_ARGS__ << " :[" << __LINE__ << ":"                \
            << __FUNCTION__ << "]" << endl                                     \
            << "    ";                                                         \
  if (DEB)                                                                     \
  dump_func(__VA_ARGS__)
template <typename T1, typename T2>
ostream &operator<<(ostream &os, pair<T1, T2> p) {
  cout << "(" << p.first << ", " << p.second << ")";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, vector<T> &vec) {
  os << "{";
  for (int i = 0; i < vec.size(); i++)
    os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
  os << "}";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, set<T> &st) {
  cout << "{";
  for (auto itr = st.begin(); itr != st.end(); itr++)
    cout << *itr << (next(itr) != st.end() ? ", " : "");
  cout << "}";
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, map<T1, T2> mp) {
  cout << "{";
  for (auto itr = mp.begin(); itr != mp.end(); itr++)
    cout << "(" << (itr->first) << ", " << (itr->second) << ")"
         << (next(itr) != mp.end() ? "," : "");
  cout << "}";
  return os;
}

void dump_func() { DUMPOUT << endl; }
template <class Head, class... Tail>
void dump_func(Head &&head, Tail &&...tail) {
  DUMPOUT << head;
  if (sizeof...(Tail) == 0) {
    DUMPOUT << " ";
  } else {
    DUMPOUT << ", ";
  }
  dump_func(std::move(tail)...);
}
template <class T> inline bool chmax(T &a, T const &b) {
  if (a >= b)
    return false;
  a = b;
  return true;
}
template <class T> inline bool chmin(T &a, T const &b) {
  if (a <= b)
    return false;
  a = b;
  return true;
}

using Int = long long;
using ll = long long;
using P = pair<Int, Int>;
using vi = vector<Int>;
using vvi = vector<vi>;
using vp = vector<P>;
using vvp = vector<vp>;

const Int INF = (1 << 30) - 10;

class DynamicModInt {
public:
  static int MOD;
  unsigned x;
  DynamicModInt() : x(0) {}
  DynamicModInt(signed sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
  DynamicModInt(signed long long sig) {
    x = sig < 0 ? sig % MOD + MOD : sig % MOD;
  }
  int get() const { return (int)x; }
  DynamicModInt &operator+=(DynamicModInt that) {
    if ((x += that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  DynamicModInt &operator-=(DynamicModInt that) {
    if ((x += MOD - that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  DynamicModInt &operator*=(DynamicModInt that) {
    x = (unsigned long long)x * that.x % MOD;
    return *this;
  }
  DynamicModInt &operator/=(DynamicModInt that) {
    return *this *= that.inverse();
  }
  DynamicModInt operator+(DynamicModInt that) const {
    return DynamicModInt(*this) += that;
  }
  DynamicModInt operator-(DynamicModInt that) const {
    return DynamicModInt(*this) -= that;
  }
  DynamicModInt operator*(DynamicModInt that) const {
    return DynamicModInt(*this) *= that;
  }
  DynamicModInt operator/(DynamicModInt that) const {
    return DynamicModInt(*this) /= that;
  }
  DynamicModInt inverse() const {
    long long a = x, b = MOD, u = 1, v = 0;
    while (b) {
      long long t = a / b;
      a -= t * b;
      std::swap(a, b);
      u -= t * v;
      std::swap(u, v);
    }
    return DynamicModInt(u);
  }
  bool operator==(DynamicModInt that) const { return x == that.x; }
  bool operator!=(DynamicModInt that) const { return x != that.x; }
  DynamicModInt operator-() const {
    DynamicModInt t;
    t.x = x == 0 ? 0 : MOD - x;
    return t;
  }
};
ostream &operator<<(ostream &st, const DynamicModInt a) {
  st << a.get();
  return st;
};
DynamicModInt operator^(DynamicModInt a, unsigned long long k) {
  DynamicModInt r = 1;
  while (k) {
    if (k & 1)
      r *= a;
    a *= a;
    k >>= 1;
  }
  return r;
}
// *より優先順位が高いため注意
int DynamicModInt::MOD;
void set_mod(signed mod) { DynamicModInt::MOD = mod; }
using mint = DynamicModInt;

void solve(long long N, long long P, string S) {
  Int ans = 0;
  if (P <= 1000) {
    vector<Int> ary(P), nxt;
    rep(i, N) {
      dump(ary);
      Int ss = Int(S[i] - '0');
      ary[ss % P]++;
      ans += ary[0];
      nxt.clear();
      nxt.resize(P);
      rep(p, P) {
        if (i == N - 1)
          break;
        ss = Int(S[i + 1] - '0');
        nxt[(p * 10 + ss) % P] += ary[p];
      }
      swap(ary, nxt);
    }
  } else {
    set_mod(P);
    mint inv = mint(1) / mint(10);
    mint co = mint(1);
    vector<mint> a(N), s(N + 1);
    rep(i, N) {
      a[i] = mint(int(S[i] - '0')) * co;
      co *= inv;
    }
    rep(i, N + 1) s[i + 1] = s[i] + a[i];
    vector<Int> ary(P);
    rep(i, N + 1) {
      ans += ary[s[i].x];
      ary[s[i].x]++;
    }
  }
  cout << ans << endl;
}

int main() {
  std::cout << std::fixed << std::setprecision(15);
  long long N;
  scanf("%lld", &N);
  long long P;
  scanf("%lld", &P);
  string S;
  cin >> S;
  solve(N, P, S);
  return 0;
}


Fixed submission:
#ifdef DEBUG_IS_VALID
#define DEB 1
#define _LIBCPP_DEBUG 0
#else
#define DEB 0
#define NDEBUG
#endif

#include <bits/stdc++.h>
using namespace std;

#define ALL(g) (g).begin(), (g).end()
#define REP(i, x, n) for (long long i = x; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define RREP(i, x, n) for (long long i = x; i >= n; i--)
#define rrep(i, n) RREP(i, n, 0)
#define pb push_back
#define fi first
#define se second
#pragma GCC optimize("-O3")

using namespace std;

#define DUMPOUT cout
#define dump(...)                                                              \
  if (DEB)                                                                     \
    DUMPOUT << "  " << #__VA_ARGS__ << " :[" << __LINE__ << ":"                \
            << __FUNCTION__ << "]" << endl                                     \
            << "    ";                                                         \
  if (DEB)                                                                     \
  dump_func(__VA_ARGS__)
template <typename T1, typename T2>
ostream &operator<<(ostream &os, pair<T1, T2> p) {
  cout << "(" << p.first << ", " << p.second << ")";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, vector<T> &vec) {
  os << "{";
  for (int i = 0; i < vec.size(); i++)
    os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
  os << "}";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, set<T> &st) {
  cout << "{";
  for (auto itr = st.begin(); itr != st.end(); itr++)
    cout << *itr << (next(itr) != st.end() ? ", " : "");
  cout << "}";
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, map<T1, T2> mp) {
  cout << "{";
  for (auto itr = mp.begin(); itr != mp.end(); itr++)
    cout << "(" << (itr->first) << ", " << (itr->second) << ")"
         << (next(itr) != mp.end() ? "," : "");
  cout << "}";
  return os;
}

void dump_func() { DUMPOUT << endl; }
template <class Head, class... Tail>
void dump_func(Head &&head, Tail &&...tail) {
  DUMPOUT << head;
  if (sizeof...(Tail) == 0) {
    DUMPOUT << " ";
  } else {
    DUMPOUT << ", ";
  }
  dump_func(std::move(tail)...);
}
template <class T> inline bool chmax(T &a, T const &b) {
  if (a >= b)
    return false;
  a = b;
  return true;
}
template <class T> inline bool chmin(T &a, T const &b) {
  if (a <= b)
    return false;
  a = b;
  return true;
}

using Int = long long;
using ll = long long;
using P = pair<Int, Int>;
using vi = vector<Int>;
using vvi = vector<vi>;
using vp = vector<P>;
using vvp = vector<vp>;

const Int INF = (1 << 30) - 10;

class DynamicModInt {
public:
  static int MOD;
  unsigned x;
  DynamicModInt() : x(0) {}
  DynamicModInt(signed sig) { x = sig < 0 ? sig % MOD + MOD : sig % MOD; }
  DynamicModInt(signed long long sig) {
    x = sig < 0 ? sig % MOD + MOD : sig % MOD;
  }
  int get() const { return (int)x; }
  DynamicModInt &operator+=(DynamicModInt that) {
    if ((x += that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  DynamicModInt &operator-=(DynamicModInt that) {
    if ((x += MOD - that.x) >= MOD)
      x -= MOD;
    return *this;
  }
  DynamicModInt &operator*=(DynamicModInt that) {
    x = (unsigned long long)x * that.x % MOD;
    return *this;
  }
  DynamicModInt &operator/=(DynamicModInt that) {
    return *this *= that.inverse();
  }
  DynamicModInt operator+(DynamicModInt that) const {
    return DynamicModInt(*this) += that;
  }
  DynamicModInt operator-(DynamicModInt that) const {
    return DynamicModInt(*this) -= that;
  }
  DynamicModInt operator*(DynamicModInt that) const {
    return DynamicModInt(*this) *= that;
  }
  DynamicModInt operator/(DynamicModInt that) const {
    return DynamicModInt(*this) /= that;
  }
  DynamicModInt inverse() const {
    long long a = x, b = MOD, u = 1, v = 0;
    while (b) {
      long long t = a / b;
      a -= t * b;
      std::swap(a, b);
      u -= t * v;
      std::swap(u, v);
    }
    return DynamicModInt(u);
  }
  bool operator==(DynamicModInt that) const { return x == that.x; }
  bool operator!=(DynamicModInt that) const { return x != that.x; }
  DynamicModInt operator-() const {
    DynamicModInt t;
    t.x = x == 0 ? 0 : MOD - x;
    return t;
  }
};
ostream &operator<<(ostream &st, const DynamicModInt a) {
  st << a.get();
  return st;
};
DynamicModInt operator^(DynamicModInt a, unsigned long long k) {
  DynamicModInt r = 1;
  while (k) {
    if (k & 1)
      r *= a;
    a *= a;
    k >>= 1;
  }
  return r;
}
// *より優先順位が高いため注意
int DynamicModInt::MOD;
void set_mod(signed mod) { DynamicModInt::MOD = mod; }
using mint = DynamicModInt;

void solve(long long N, long long P, string S) {
  Int ans = 0;
  if (P <= 500) {
    vector<Int> ary(P), nxt;
    rep(i, N) {
      dump(ary);
      Int ss = Int(S[i] - '0');
      ary[ss % P]++;
      ans += ary[0];
      nxt.clear();
      nxt.resize(P);
      rep(p, P) {
        if (i == N - 1)
          break;
        ss = Int(S[i + 1] - '0');
        nxt[(p * 10 + ss) % P] += ary[p];
      }
      swap(ary, nxt);
    }
  } else {
    set_mod(P);
    mint inv = mint(1) / mint(10);
    mint co = mint(1);
    vector<mint> a(N), s(N + 1);
    rep(i, N) {
      a[i] = mint(int(S[i] - '0')) * co;
      co *= inv;
    }
    rep(i, N + 1) s[i + 1] = s[i] + a[i];
    vector<Int> ary(P);
    rep(i, N + 1) {
      ans += ary[s[i].x];
      ary[s[i].x]++;
    }
  }
  cout << ans << endl;
}

int main() {
  std::cout << std::fixed << std::setprecision(15);
  long long N;
  scanf("%lld", &N);
  long long P;
  scanf("%lld", &P);
  string S;
  cin >> S;
  solve(N, P, S);
  return 0;
}