#include <bits/stdc++.h>

using namespace std;
#define rep(x, n)          for (int x = 0; x < n; x++)
#define REP(x, a, b)       for (int x = a; x <= b; x++)
#define all(container)     (container).begin(), container.end()
#define rall(container)    (container).begin(), container.end()
#define sz(container)      (int) (container).size()

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

#ifdef LOCAL_DEFINE
    #include "DEBUG.hpp"
#else
    #define debug(...) 0
#endif
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }

template<int Mod = 998244353>
class Modular {
private:
    int value;
    static int mod_inverse(int a, int mod) {
        a %= mod;
        assert(a);
        if (a == 1)
            return 1;
        return int(mod - ll(mod_inverse(mod, a)) * ll(mod) / a);
    }
public:
    Modular(): value(0) {}
    Modular(ll val):value(val % Mod) { if (value < 0) value += Mod;}
    friend std::ostream& operator << (std::ostream& out, const Modular& n) {return out << n.value;}
    friend std::istream& operator >> (std::istream& in, Modular& n) {ll v; in >> v; n = Modular(v); return in;}
    explicit operator int() const { return this->value;}
    friend bool operator == (const Modular& a, const Modular& b) {return a.value == b.value;}
    friend bool operator != (const Modular& a, const Modular& b) {return a.value != b.value;}

    Modular inverse() const {
        Modular ret;
        ret.value = mod_inverse(this->value, Mod);
        return ret;
    }
    Modular neg() const {
        Modular ret;
        ret.value = this->value ? Mod - this->value : 0;
        return ret;
    }
    Modular operator- (){return neg();}
    Modular& operator++ () {this->value++; if (this->value == Mod) this->value = 0; return *this;}
    Modular& operator-- () {if (this->value == 0) this->value = Mod; --this->value; return *this;}
    Modular& operator+= (const Modular& other) {this->value += other.value; if (this->value >= Mod) this->value -= Mod; return *this;}
    Modular& operator-= (const Modular& other) {this->value -= other.value; if (this->value < 0) this->value += Mod; return *this;}
    Modular& operator*= (const Modular& other) {this->value = ll(this->value) * ll(other.value) % Mod; return *this;}    
    Modular& operator/= (const Modular& other) {return *this *= other.inverse();}
    friend Modular operator ++ (Modular& a, int) {Modular ret = a; ++a; return ret;}
    friend Modular operator -- (Modular& a, int) {Modular ret = a; --a; return ret;}
    friend Modular operator + (const Modular& a, const Modular& b) {Modular ret = a; ret += b; return ret;}
    friend Modular operator - (const Modular& a, const Modular& b) {Modular ret = a; ret -= b; return ret;}
    friend Modular operator * (const Modular& a, const Modular& b) {Modular ret = a; ret *= b; return ret;}
    friend Modular operator / (const Modular& a, const Modular& b) {Modular ret = a; ret /= b; return ret;}
};
using Mint = Modular<2019>;

template<typename T1, typename T2>
T1 epow(T1 a, T2 b) {
    assert(b >= 0);
    T1 ret = 1;
    while (b) {
        if (b & 1)
            ret *= a;
        a *= a;
        b >>= 1;
    }
    return ret;
}

int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    string s;
    cin>>s;
    reverse(all(s));
    vector<Mint> pre(sz(s));
    pre[0]=(s[0]-'0');
    ll ans=0;
    map<int,ll> mp;
    mp[s[0]-'0']=1;
    REP(i,1,sz(s)-1){
        pre[i]=(s[i]-'0')*epow<Mint,int>(10,i)+pre[i-1];
        ++mp[int(pre[i])];
    }
    for(auto&x:mp){
        ans+=(x.second*(x.second-1))/2;
    }
    ans+=mp[0];
    cout<<ans<<'\n';
    return 0;
}

Measured memory_bytes: 4396