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

typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> PL;

const ll MOD = 1000000007;
const ll INF_LL = (ll)1000000007 * 1000000007;
const int INF_INT = (int)1000000007;
const double PI = 3.14159265358979323846;

const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; i--)
#define irep(itr, st) for (auto itr = (st).begin(); itr != (st).end(); ++itr)
#define irrep(itr, st) for (auto itr = (st).rbegin(); itr != (st).rend(); ++itr)

#define m0(x) memset((x), 0, sizeof((x)))
#define m1(x) memset((x), -1, sizeof((x)))

// xにはvectorなどのコンテナ
#define ALL(x) (x).begin(), (x).end()  // sortなどの引数を省略したい
#define RALL(x) (x).rbegin(), (x).rend()  // sortなどの引数を省略したい
#define SIZE(x) ((ll)(x).size())     // sizeをsize_tからllに直しておく
#define MAX(x) *max_element(ALL(x))  //最大値を求める
#define MIN(x) *min_element(ALL(x))  //最小値を求める
#define all(x) (x).begin(), (x).end()

//略記
#define pb emplace_back  // vectorヘの挿入
#define mp make_pair     // pairのコンストラクタ
#define F first          // pairの一つ目の要素
#define S second         // pairの二つ目の要素

#define BITCOUNT __builtin_popcount
#define BITCOUNT_LL(x) __builtin_popcountll(x)

#define perm(c)             \
  sort(all(c));             \
  for (bool c##p = 1; c##p; \
       c##p = next_permutation(all(c)))  //順列 123 132 213 231 312 321

#define BIT(n) (1LL << (n))

#ifdef DEBUG
#define PRINT(A) std::cout << (#A) << ": " << (A) << std::endl;
#else
#define PRINT(A)
#endif

//入力高速化
struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

template <class T>
inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template <class T>
inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

signed __main() {
  string S;
  cin >> S;
  int length = S.length();

  int ans = 0;

  // sum(i) iまで足した時の累積和。
  vector<int> sum(length+1);
  //累積和で、何も選ばれないときを追加するのを忘れずに。
  sum[0] = 0;
  int dig = 1;
  const int m = 2019;
  //各桁の合計を求める。123456であれば、123400mod2019 == 1234mod2019となる。→2019と10が素のため。
  //123400のmod2019を求めるのであれば、100000と20000と3000と400のmod2019を足せばOK。
  //なので、i桁までのmodの累積和を求めておき、後で組み合わせの数を求める。

  reverse(all(S));  //入れ替えておくと、S[i]*10^i とできるからシンプル。 S[lendgh-i]*10^iでもOK。

  for (int i = 0; i < length; i++) {
    sum[i + 1] = (sum[i] + dig * (S[i] - '0')) % m;
    dig = dig * 10 % m;
    PRINT(sum[i])
    // PRINT(dig)
  }

  //mod2019が共通になってる組み合わせの数を足し合わせる→ans
  rep(i, m) {
    int count = 0;
    rep(j, length+1) {
      if (i == sum[j]) {
        count++;
      }
    }
    if (count == 0) continue;
    ans += count * (count - 1) / 2;
  }


  cout << ans << endl;
}

//別解 こっちの方が効率良い。
signed main() {
  string S;
  cin >> S;
  int length = S.length();

  int ans = 0;

  // sum(i) iまで足した時の累積和。
  vector<int> sum(length + 1);
  //累積和で、何も選ばれないときを追加するのを忘れずに。
  sum[0] = 0;
  int dig = 1;
  const int m = 2019;
  //各桁の合計を求める。123456であれば、123400mod2019 ==
  //1234mod2019となる。→2019と10が素のため。
  // 123400のmod2019を求めるのであれば、100000と20000と3000と400のmod2019を足せばOK。
  //なので、i桁までのmodの累積和を求めておき、後で組み合わせの数を求める。

  reverse(all(S));  //入れ替えておくと、S[i]*10^i とできるからシンプル。
                    //S[lendgh-i]*10^iでもOK。
  vector<int> cnt(m);
  cnt[0]++;
  for (int i = 0; i < length; i++) {
    sum[i + 1] = (sum[i] + dig * (S[i] - '0')) % m;
    dig = dig * 10 % m;
    //ここまでで、何回、このmod2019になっているかを確認して、それらとの組み合わせ回数を足す。
    ans += cnt[sum[i+1]];
    //自分自身も、次以降のために足しておく。
    cnt[sum[i+1]] ++;
  }

  cout << ans << endl;
}

Measured memory_bytes: 4368