Problem p01443 (C++) — buggy submission, verdict: Runtime Error

#include "bits/stdc++.h"
#include <unordered_map>
#pragma warning(disable : 4996)
using namespace std;

int mod = 1000000007;
struct Mod {
public:
  int num;
  Mod() : num(0) { ; }
  Mod(long long int n) : num((n % mod + mod) % mod) { ; }
  Mod(int n) : num((n % mod + mod) % mod) { ; }
  operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a + b.num); }
Mod operator+(const Mod a, const long long int b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) {
  return Mod((mod + a.num - b.num) % mod);
}
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) {
  return Mod(((long long)a.num * b.num) % mod);
}
Mod operator*(const long long int a, const Mod b) { return Mod(a * b.num); }
Mod operator*(const Mod a, const int b) { return Mod(b) * a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
  if (n == 0)
    return Mod(1);
  Mod res = (a * a) ^ (n / 2);
  if (n % 2)
    res = res * a;
  return res;
}
Mod mod_pow(const Mod a, const int n) {
  if (n == 0)
    return Mod(1);
  Mod res = mod_pow((a * a), (n / 2));
  if (n % 2)
    res = res * a;
  return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
  assert(b.num != 0);
  return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
  assert(b.num != 0);
  return Mod(a) * inv(b);
}
Mod operator/=(Mod &a, const Mod b) {
  assert(b.num != 0);
  return a = a * inv(b);
}

#define MAX_MOD_N 1024000

Mod fact[MAX_MOD_N], factinv[MAX_MOD_N];
void init() {
  fact[0] = Mod(1);
  factinv[0] = 1;
  for (int i = 0; i < MAX_MOD_N - 1; ++i) {
    fact[i + 1] = fact[i] * Mod(i + 1);
    factinv[i + 1] = factinv[i] / Mod(i + 1);
  }
}
Mod comb(const int a, const int b) {
  return fact[a] * factinv[b] * factinv[a - b];
}

#define Seg_Max_N (1 << 18)
// update(l,r,v) := [l,r]の区間に対してvを一様に足す. k,a,bは飾り

struct NODE {
  long long int sum; // 更新された値.
                     // この値を参照する時は評価が完全に完了しているようにする.
  long long int lazy; // 遅延されている値を保存している
  NODE() { sum = lazy = 0; }
};

NODE seg[2 * Seg_Max_N];

// inlineつけないと大変なことになるよ!(遅い)
inline void lazy_evaluate_node(int k, int a, int b) {
  seg[k].sum += seg[k].lazy * (b - a + 1);
  seg[k].sum %= mod;
  if (k < Seg_Max_N) { // 2*k(左の子番号) < 2*N (節点の数) のイメージで.
                       // 末端ノードじゃなきゃ伝搬するのと等価.
    seg[2 * k].lazy += seg[k].lazy; // 次は君が伝搬してね☆って感じ.
    seg[2 * k].lazy %= mod;
    seg[2 * k + 1].lazy += seg[k].lazy;
    seg[2 * k + 1].lazy %= mod;
  }
  seg[k].lazy = 0;
}

inline void update_node(
    int k) { // kの子が既に評価されていることが前提.
             // 末端以外のときしか呼び出さないような位置に書くのでif文要らない.
  seg[k].sum = seg[2 * k].sum + seg[2 * k + 1].sum;
  seg[k].sum %= mod;
}

// update(l,r,v) := [l,r]を更新する. 区間は1-indexed.
void update(int l, int r, int v, int k = 1, int a = 1, int b = Seg_Max_N) {
  if (l < 0 || r < 0)
    assert(false);
  lazy_evaluate_node(
      k, a, b); // とりあえず辿ったノードは都合がいいので伝搬しとけ精神.

  if (b < l || r < a) //[a,b]と[l,r]が交差している場合
    return;
  if (l <= a && b <= r) { // [l,r]が[a,b]を完全に含んでいる場合
    seg[k].lazy += v;
    seg[k].lazy %= mod;
    lazy_evaluate_node(k, a, b); // 一回遅延評価しとかないと都合悪いので.
    return;
  }

  int m = (a + b) / 2;
  update(l, r, v, 2 * k, a, m);
  update(l, r, v, 2 * k + 1, m + 1, b);
  update_node(k);
}

// get(l,r) := [l,r]に対するクエリの答えを得る. 区間は1-indexed.
long long int get(int l, int r, int k = 1, int a = 1, int b = Seg_Max_N) {
  if (l < 0 || r < 0)
    assert(false);
  lazy_evaluate_node(
      k, a, b); // とりあえず辿ったノードは都合がいいので伝搬しとけ精神.

  if (b < l || r < a) //[a,b]と[l,r]が交差している場合
    return 0;

  if (l <= a && b <= r) { // [l,r]が[a,b]を完全に含んでいる場合
    return seg[k].sum;
  }

  int m = (a + b) / 2;
  Mod vl = get(l, r, 2 * k, a, m);
  Mod vr = get(l, r, 2 * k + 1, m + 1, b);
  update_node(k);
  return vl + vr;
}

long long int powint(long long int a, long long int b) {
  assert(b >= 0);
  if (b == 0)
    return 1;
  if (b == 1)
    return a;
  long long int ans = 1;
  long long int aa = powint(a, b / 2);
  ans *= aa * aa;
  if (b % 2)
    ans *= a;
  return ans;
}

int main() {
  while (1) {
    for (int i = 0; i < 2 * Seg_Max_N; ++i) {
      seg[i].lazy = 0;
      seg[i].sum = 0;
    }
    long long int A, B, P;
    cin >> A >> B >> P;
    if (!A)
      break;
    mod = P;
    update(1, B - A + 1, 1);

    for (int id = 0; id < B - A; ++id) {
      long long int num = id + A;
      long long int adp = get(id + 1, id + 1);
      long long int now = num;
      int keta = (to_string(now).size());
      while (1) {
        long long int amin = now;
        long long int amax = min(powint(10, keta) - 1, B);
        if (amin > amax)
          break;
        if (amin == num)
          amin++;

        update(amin - A + 1, amax - A + 1, adp);
        now = now * 10;
        keta++;
      }
    }
    Mod ans = get(1, B - A + 1);
    cout << ans << endl;
  }
  return 0;
}

Error: -8

Fixed submission:

#include "bits/stdc++.h"
#include <unordered_map>
#pragma warning(disable : 4996)
using namespace std;

int mod = 1000000007;
struct Mod {
public:
  int num;
  Mod() : num(0) { ; }
  Mod(long long int n) : num((n % mod + mod) % mod) { ; }
  Mod(int n) : num((n % mod + mod) % mod) { ; }
  operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a + b.num); }
Mod operator+(const Mod a, const long long int b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) {
  return Mod((mod + a.num - b.num) % mod);
}
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) {
  return Mod(((long long)a.num * b.num) % mod);
}
Mod operator*(const long long int a, const Mod b) { return Mod(a * b.num); }
Mod operator*(const Mod a, const int b) { return Mod(b) * a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
  if (n == 0)
    return Mod(1);
  Mod res = (a * a) ^ (n / 2);
  if (n % 2)
    res = res * a;
  return res;
}
Mod mod_pow(const Mod a, const int n) {
  if (n == 0)
    return Mod(1);
  Mod res = mod_pow((a * a), (n / 2));
  if (n % 2)
    res = res * a;
  return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
  assert(b.num != 0);
  return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
  assert(b.num != 0);
  return Mod(a) * inv(b);
}
Mod operator/=(Mod &a, const Mod b) {
  assert(b.num != 0);
  return a = a * inv(b);
}

#define MAX_MOD_N 1024000

Mod fact[MAX_MOD_N], factinv[MAX_MOD_N];
void init() {
  fact[0] = Mod(1);
  factinv[0] = 1;
  for (int i = 0; i < MAX_MOD_N - 1; ++i) {
    fact[i + 1] = fact[i] * Mod(i + 1);
    factinv[i + 1] = factinv[i] / Mod(i + 1);
  }
}
Mod comb(const int a, const int b) {
  return fact[a] * factinv[b] * factinv[a - b];
}

#define Seg_Max_N (1 << 17)
// update(l,r,v) := [l,r]の区間に対してvを一様に足す. k,a,bは飾り

struct NODE {
  long long int sum; // 更新された値.
                     // この値を参照する時は評価が完全に完了しているようにする.
  long long int lazy; // 遅延されている値を保存している
  NODE() { sum = lazy = 0; }
};

NODE seg[2 * Seg_Max_N];

// inlineつけないと大変なことになるよ!(遅い)
inline void lazy_evaluate_node(int k, int a, int b) {
  seg[k].sum += seg[k].lazy * (b - a + 1);
  seg[k].sum %= mod;
  if (k < Seg_Max_N) { // 2*k(左の子番号) < 2*N (節点の数) のイメージで.
                       // 末端ノードじゃなきゃ伝搬するのと等価.
    seg[2 * k].lazy += seg[k].lazy; // 次は君が伝搬してね☆って感じ.
    seg[2 * k + 1].lazy += seg[k].lazy;
  }
  seg[k].lazy = 0;
}

inline void update_node(
    int k) { // kの子が既に評価されていることが前提.
             // 末端以外のときしか呼び出さないような位置に書くのでif文要らない.
  seg[k].sum = seg[2 * k].sum + seg[2 * k + 1].sum;
  seg[k].sum %= mod;
}

// update(l,r,v) := [l,r]を更新する. 区間は1-indexed.
void update(int l, int r, int v, int k = 1, int a = 1, int b = Seg_Max_N) {
  if (l < 0 || r < 0)
    assert(false);
  lazy_evaluate_node(
      k, a, b); // とりあえず辿ったノードは都合がいいので伝搬しとけ精神.

  if (b < l || r < a) //[a,b]と[l,r]が交差している場合
    return;
  if (l <= a && b <= r) { // [l,r]が[a,b]を完全に含んでいる場合
    seg[k].lazy += v;
    lazy_evaluate_node(k, a, b); // 一回遅延評価しとかないと都合悪いので.
    return;
  }

  int m = (a + b) / 2;
  update(l, r, v, 2 * k, a, m);
  update(l, r, v, 2 * k + 1, m + 1, b);
  update_node(k);
}

// get(l,r) := [l,r]に対するクエリの答えを得る. 区間は1-indexed.
int get(int l, int r, int k = 1, int a = 1, int b = Seg_Max_N) {
  if (l < 0 || r < 0)
    assert(false);
  lazy_evaluate_node(
      k, a, b); // とりあえず辿ったノードは都合がいいので伝搬しとけ精神.

  if (b < l || r < a) //[a,b]と[l,r]が交差している場合
    return 0;

  if (l <= a && b <= r) { // [l,r]が[a,b]を完全に含んでいる場合
    return seg[k].sum;
  }

  int m = (a + b) / 2;
  Mod vl = get(l, r, 2 * k, a, m);
  Mod vr = get(l, r, 2 * k + 1, m + 1, b);
  update_node(k);
  return vl + vr;
}

long long int powint(long long int a, long long int b) {
  assert(b >= 0);
  if (b == 0)
    return 1;
  if (b == 1)
    return a;
  long long int ans = 1;
  long long int aa = powint(a, b / 2);
  ans *= aa * aa;
  if (b % 2)
    ans *= a;
  return ans;
}

int main() {
  while (1) {
    for (int i = 0; i < 2 * Seg_Max_N; ++i) {
      seg[i].lazy = 0;
      seg[i].sum = 0;
    }
    long long int A, B, P;
    cin >> A >> B >> P;
    mod = P;
    update(1, B - A + 1, 1);

    for (int id = 0; id < B - A; ++id) {
      long long int num = id + A;
      long long int adp = get(id + 1, id + 1);
      long long int now = num;
      int keta = (to_string(now).size());
      while (1) {
        long long int amin = now;
        long long int amax = min(powint(10, keta) - 1, B);
        if (amin > amax)
          break;
        if (amin == num)
          amin++;

        update(amin - A + 1, amax - A + 1, adp);
        now = now * 10;
        keta++;
      }
    }
    Mod ans = get(1, B - A + 1);
    cout << ans << endl;
  }
  return 0;
}