#include <iostream> // cout, endl, cin
#include <string> // string, to_string, stoi
#include <vector> // vector
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <utility> // pair, make_pair
#include <tuple> // tuple, make_tuple
#include <cstdint> // int64_t, int*_t
#include <cstdio> // printf
#include <map> // map
#include <queue> // queue, priority_queue
#include <set> // set
#include <stack> // stack
#include <deque> // deque
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <bitset> // bitset
#include <cctype> // isupper, islower, isdigit, toupper, tolower
#include<math.h>
#include<iomanip>
#include<functional>
using namespace std;

#define ll long long
using vt = ll; //ここで数値の型を変えられる
#define rep(i, n) for (vt i = 0; i < (vt)(n); i++)
#define reps(i, s, n) for(vt i = (vt) (s); i < (vt) (n); i++) 
#define all(v) v.begin(), v.end()
#define P pair<ll, ll>
const ll  MOD = 1000000007;

vt pow_mod_rep_square(vt n, vt p, vt mod) { //mod付き
	if (p == 0) return 1;
	else if (p % 2 == 0) {
		vt t = pow_mod_rep_square(n, p / 2, mod);
		return t * t % mod;
	}
	else return n * pow_mod_rep_square(n, p - 1, mod) % mod;
}

vt inv_Felmat(vt a, vt mod) {
	return pow_mod_rep_square(a, mod - 2, mod);
}

int main() {
	string s;
	cin >> s;
	if (s.size() < 5) {
		cout << 0;
		return 0;
	}
	reverse(all(s));
	vector<int> v(s.size());
	rep(i, s.size()) {
		int x = s.at(i) - '0';
		v.at(i) = (x * pow_mod_rep_square(10, i, 2019)) % 2019;
	}
	reps(i, 1, s.size()) {
		v.at(i) += v.at(i - 1);
		v.at(i) %= 2019;
	}	
	int ans = 0;
	reps(i, 4, s.size()) if (v.at(i) == 0) ans++;
	rep(i, s.size() - 4) {
		reps(j, i + 4, s.size()){
			if (((v.at(j) - v.at(i)) * inv_Felmat(pow_mod_rep_square(10, j - i, 2019), 2019) % 2019)== 0) {
				ans++;
			}
		}
	}
	cout << ans;
	return 0;
}