#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<map>
#include<set>
#include<queue>
#include<string>

using namespace std;

#define REP(i, n) for(int i = 0; i < n; i++)
#define REPR(i, n) for(int i = n; i >= 0; i--)
#define FOR(i, m, n) for(int i = m; i < n; i++)
#define ALL(a) (a).begin(),(a).end()
#define PI 3.141592653589793238
#define INF 1050000000
#define INFL (long long)(4e18)

using vi = vector<int>;

template<class T>
struct Edge {
    int to;
    T cost;
    Edge() {};
    Edge(int to, T cost) : to(to), cost(cost) {};
};

template<class T>
class Graph {
    int n;
    bool directed;
    vector<vector<Edge<T>>> edges;
public:

    Graph(int n, bool directed) :n(n), directed(directed), edges(vector<vector<Edge<T>>>(n)){};
    Graph() {};

    void add(int from,int to, T cost) {
        edges[from].emplace_back(to, cost);
        if(!directed){
            edges[to].emplace_back(from,cost);
        }
    }

    int size() {
        return n;
    }
};




int main() {

    string S;

    cin >> S;

    vi sum(2019);

    REP(i,2019)sum[i] = 0;

    reverse(ALL(S));

    int tmp = 0;
    int keta = 1;

    REP(i,S.size()){
        int c = S[i] - '0';
        sum[(tmp + keta * c % 2019)%2019]++;
        tmp = (tmp + keta * c % 2019) % 2019;
        keta *= 10; keta %= 2019;
   }

    long long int ans = 0;

    REP(i,2019){
        ans += sum[i] * (sum[i]-1) / 2;
    }
    
    

    cout << ans+sum[0] << endl;

    return 0;
}