#include <bits/stdc++.h>
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/tree_policy.hpp>
     
    using namespace std;
    using namespace __gnu_pbds;
     
    void debug_out() { cerr << endl; }
    template<class T> ostream& prnt(ostream& out, T v) { out << v.size() << '\n'; for(auto e : v) out << e << ' '; return out;}
    template<class T> ostream& operator<<(ostream& out, vector <T> v) { return prnt(out, v); }
    template<class T> ostream& operator<<(ostream& out, set <T> v) { return prnt(out, v); }
    template<class T1, class T2> ostream& operator<<(ostream& out, map <T1, T2> v) { return prnt(out, v); }
    template<class T1, class T2> ostream& operator<<(ostream& out, pair<T1, T2> p) { return out << '(' << p.st << ' ' << p.nd << ')'; }
    template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) { cerr << " " << H; debug_out(T...);}
     
    #define dbg(...) cerr << #__VA_ARGS__ << " ->", debug_out(__VA_ARGS__)
    #define dbg_v(x, n) do{cerr<<#x"[]: ";for(int _=0;_<n;++_)cerr<<x[_]<<" ";cerr<<'\n';}while(0)
    #define dbg_ok cerr<<"OK!\n"
    #define  st first
    #define  nd second
    #define int long long  
     
    template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
     
    typedef cc_hash_table<int, int, hash<int > > ht;
     
    const int  M    = 998244353;
    const int  MAXN = 10005 ;
    const int   INF  = 0x3F3F3F3F  ; // long long inf
    const long double eps = 1.084202e-19;
 
    int32_t main(){
         ios_base::sync_with_stdio(false);
         cin.tie(NULL);
         string s ;  
         cin >> s ; 
         int n = s.size() ; 
         int p= 2019;
         map<int, int> mp;
         int ans = 0 ;
		++mp[0];
		int t=0, p2=1;
		for(int i=n-1; ~i; --i) {
			t=(t+(s[i]-'0')*p2)%p;
			ans+=mp[t];
			mp[t]++;
			p2=p2*10%p;
		}
        cout<<ans;
        
       
    }