stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;



#define rep(i,n) for(i = 0;i < n;++i)

#define all(v) v.begin(), v.end()

using ll = long long;



int main()

{

    ll i,j;

    string s;

    cin >> s;

    ll n = s.size();

    vector<ll> spare(n);

    vector<ll> vs(n);

    map<ll,ll> mp;

    for(i = 0;i < 2019;++i){

        mp[i] = 0;

    }

    for(i = 0;i < n;++i){

        vs.at(i) = s.at(i) -'0';

    }

    spare.at(n-1) = vs.at(n-1);

    ++mp[spare.at(n-1)];

    ++mp[0];

    vector<ll> spare10(n,1);

    spare10.at(n-1) = 1;

    for(i = 1;i < n;++i){

        spare10.at(n-1-i) = spare10.at(n-i)*10%2019;

        spare.at(n-1-i) = (vs.at(n-1-i)*spare10.at(n-1-i) + spare.at(n-i))%2019;

        ++mp[spare.at(n-1-i)];

    }

    ll ans = 0;

    for(auto x:mp){

        ll tmp = x.second;

        ans += tmp*(tmp-1)/2;

    }

    cout << ans << endl;

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.275370956173344x):
#include <bits/stdc++.h>

using namespace std;



#define rep(i,n) for(i = 0;i < n;++i)

#define all(v) v.begin(), v.end()

using ll = long long;



int main()

{

    ll i,j;

    string s;

    cin >> s;

    ll n = s.size();

    vector<ll> spare(n);

    vector<ll> vs(n);

    vector<ll> mp(2019,0);

    for(i = 0;i < n;++i){

        vs.at(i) = s.at(i) -'0';

    }

    spare.at(n-1) = vs.at(n-1);

    ++mp.at(spare.at(n-1));

    ++mp.at(0);

    vector<ll> spare10(n,1);

    spare10.at(n-1) = 1;

    for(i = 1;i < n;++i){

        spare10.at(n-1-i) = spare10.at(n-i)*10%2019;

        spare.at(n-1-i) = (vs.at(n-1-i)*spare10.at(n-1-i) + spare.at(n-i))%2019;

        ++mp.at(spare.at(n-1-i));

    }

    ll ans = 0;

    for(auto x:mp){

        ans += x*(x-1)/2;

    }

    cout << ans << endl;

    return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;



#define int long long



#define ii pair<int, int>

#define fi first

#define sc second

#define set unordered_set

#define map unordered_map

#define all(x) (x).begin(), (x).end()



signed main() {

#ifdef _DEBUG

	freopen("in", "r", stdin);

#endif

	ios::sync_with_stdio(0); cin.tie(0);

	string str; cin >> str;

  int sum = 0, ans = 0;

  vector<int> cnt(2019, 0), tmp(2019, 0);

  cnt[0] = 1;

  for (int i = 0; i < str.size(); i++) {

    for (int j = 0; j < 2019; j++) {

      tmp[j] = 0;

    }

    for (int j = 0; j < 2019; j++) {

      tmp[(j * 10) % 2019] = cnt[j];

    }

    for (int j = 0; j < 2019; j++) {

      cnt[j] = tmp[j];

    }

    sum = (sum * 10 + (str[i] - '0')) % 2019;

    ans += cnt[sum];

    cnt[sum]++;

  }

  cout << ans << '\n';

}


// Faster C++ solution for the same problem (measured speedup: 1.2096415624549508x):
#include <bits/stdc++.h>

using namespace std;



// ----------- define --------------

#define int long long

#define ii pair<int,int>

#define fi first

#define sc second

#define all(x) (x).begin(),(x).end()

// ---------------------------------



#define pow abcdef

int pow(int a, int b) {

  if (b == 0) return 1;

  int t = pow(a, b / 2);

  t = (t * t) % 2019;

  if (b % 2) return (a * t) % 2019;

  return t;

}



void MAIN() {

  string s;

  cin >> s;

  reverse(all(s));

  vector<int> a(s.size());

  int ans = 0;

  map<int, int> m; m[0] = 1;

  for (int i = 0; i < s.size(); i++) {

    a[i] = (s[i] - '0') * pow(10, i);

    if (i) a[i] += a[i - 1];

    a[i] %= 2019;

    ans += m[a[i]];

    m[a[i]]++;

  }

  cout << ans << '\n';

}



signed main() {

  ios::sync_with_stdio(0); cin.tie(0);

  int T = 1;

  // cin >> T;

  while (T--) MAIN();

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define ALL(a)  (a).begin(),(a).end()

#define sz(x) int(x.size())

using namespace std;

typedef long long ll;

typedef pair<int, int> P;

typedef pair<long long, long long> Pll;

typedef vector<int> vi;

typedef vector<vector<int>> vvi;

typedef vector<long long> vll;

typedef vector<vector<long long>> vvll;

template <typename T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }

template <typename T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

const long long INF = 1LL << 60;

const int INT_INF = 1 << 30;

const double PI = acos(-1.0);

#define MOD 1000000009LL

#define endl "\n"



struct COM{

  ll modpow(ll x, ll nn){

    ll res = 1;

    while(nn > 0){

      if(nn & 1) res = res * x % MOD;

      x = x * x % MOD;

      nn >>= 1;

    }

    return res;

  }

  vll fact, ifact;

  COM(ll n): fact(n+1), ifact(n+1){

    assert(n < MOD);

    fact[0] = 1LL;

    for(ll i = 1; i <= n; i++) fact[i] = fact[i-1]*i%MOD;

    ifact[n] = modpow(fact[n], MOD-2);

    for(ll i = n; i >= 1; i--) ifact[i-1] = ifact[i]*i%MOD;

  }

  ll operator()(int n, int k){

    if(k < 0 || k > n) return 0;

    return fact[n]*ifact[k]%MOD*ifact[n-k]%MOD;

  }

};



int main(){

  ios::sync_with_stdio(false);

  cin.tie(nullptr);

  srand((unsigned)time(NULL));

  COM c(200010);

  string S;

  cin >> S;

  ll N = S.size();

  vll count(2019, 0LL);

  ll num = 0LL;

  ll keta = 1LL;

  for(int i = N-1; i >= 0; i--){

    num += keta * (S.at(i)-'0') % 2019;

    num %= 2019;

    count.at(num)++;

    keta *= 10;

    keta %= 2019;

  }

  count.at(0)++;

  ll ans = 0;

  for(int i = 0; i < 2019; i++){

    ans += c(count.at(i), 2);

  }

  cout <<ans << endl;

}

// Faster C++ solution for the same problem (measured speedup: 6.606646536051076x):
#include <bits/stdc++.h>

#define ALL(a)  (a).begin(),(a).end()

#define sz(x) int(x.size())

using namespace std;

typedef long long ll;

typedef pair<int, int> P;

typedef pair<long long, long long> Pll;

typedef vector<int> vi;

typedef vector<vector<int>> vvi;

typedef vector<long long> vll;

typedef vector<vector<long long>> vvll;

template <typename T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }

template <typename T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

const long long INF = 1LL << 60;

const int INT_INF = 1 << 30;

const double PI = acos(-1.0);

#define MOD 1000000009LL

#define endl "\n"



int main(){

  ios::sync_with_stdio(false);

  cin.tie(nullptr);

  srand((unsigned)time(NULL));

  string S;

  cin >> S;

  ll N = S.size();

  vll count(2019, 0LL);

  ll num = 0LL;

  ll keta = 1LL;

  for(int i = N-1; i >= 0; i--){

    num += keta * (S.at(i)-'0') % 2019;

    num %= 2019;

    count.at(num)++;

    keta *= 10;

    keta %= 2019;

  }

  count.at(0)++;

  ll ans = 0;

  auto func = [](ll n){

    return n * (n-1) / 2LL;

  };

  for(int i = 0; i < 2019; i++){

    ans += func(count.at(i));

  }

  cout <<ans << endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;











typedef long long ll;

typedef long double ld;





ll a[2][2019];











int main(){

	ios::sync_with_stdio(0);

    cin.tie(0);cout.tie(0);

    string s;

    cin>>s;

    ll ans = 0;

    int n = s.size();

    for(int x = 0;x < n;x++){

    	for(int i = 0;i < 2019;i++){

    		a[1][(i*10 + s[x]-'0' + 2019) % 2019] += a[0][i];

		}

		a[1][s[x]-'0']++;

		for(int i = 0;i < 2019;i++){

			a[0][i] = a[1][i];

			a[1][i] = 0;

		}

		ans += a[0][0];

	}

	cout<<ans<<endl;

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.1833904960042403x):
#include <bits/stdc++.h>

using namespace std;











typedef long long ll;

typedef long double ld;





ll a[2019];











int main(){

	ios::sync_with_stdio(0);

    cin.tie(0);cout.tie(0);

    string s;

    cin>>s;

    ll ans = 0;

    int n = s.size();

    int x = 1;

    int mod = 0;

    a[0] = 1;

    for(int i = n-1;i >= 0;i--){

    	mod = (x*(s[i]-'0') + mod) % 2019;

    	x = (x*10) % 2019;

    	a[mod]++;

	}

	for(int i = 0;i < 2019;i++){

		ans += (a[i]-1) * a[i] / 2;

	}

	cout<<ans<<endl;

    return 0;

}
// Slower C++ solution:
#include <algorithm>

#include <cassert>

#include <iostream>

#include <vector>

using namespace std;



template<typename T> ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }

template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }



void dbg_out() { cerr << endl; }

template<typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cerr << ' ' << H; dbg_out(T...); }



#ifdef NEAL_DEBUG

#define dbg(...) cerr << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)

#else

#define dbg(...)

#endif





const int M = 2019;



int main() {

    ios::sync_with_stdio(false);

#ifndef NEAL_DEBUG

    cin.tie(nullptr);

#endif



    string S;

    cin >> S;

    int N = S.size();

    vector<int64_t> dp(M, 0);

    int64_t ans = 0;



    for (int i = 0; i < N; i++) {

        vector<int64_t> next_dp(M, 0);



        for (int m = 0; m < M; m++)

            next_dp[(10 * m + S[i] - '0') % M] += dp[m];



        next_dp[S[i] - '0']++;

        dp = next_dp;

        ans += dp[0];

    }



    cout << ans << endl;

}


// Faster C++ solution for the same problem (measured speedup: 1.2401408904913007x):
#include <algorithm>

#include <cassert>

#include <iostream>

#include <vector>

using namespace std;



template<typename T> ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }

template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }



void dbg_out() { cerr << endl; }

template<typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cerr << ' ' << H; dbg_out(T...); }



#ifdef NEAL_DEBUG

#define dbg(...) cerr << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)

#else

#define dbg(...)

#endif





const int M = 2019;



int main() {

    ios::sync_with_stdio(false);

#ifndef NEAL_DEBUG

    cin.tie(nullptr);

#endif



    string S;

    cin >> S;

    int N = int(S.size());



    vector<int> freq(M, 0);

    freq[0] = 1;



    int value = 0, p10 = 1;

    int64_t total = 0;



    for (int i = N - 1; i >= 0; i--) {

        value = (value + p10 * (S[i] - '0')) % M;

        p10 = 10 * p10 % M;

        total += freq[value];

        freq[value]++;

    }



    cout << total << '\n';

}
// Slower C++ solution:
#include <algorithm>

#include <cassert>

#include <iostream>

#include <vector>

using namespace std;



template<typename T> ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }

template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }



void dbg_out() { cerr << endl; }

template<typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cerr << ' ' << H; dbg_out(T...); }



#ifdef NEAL_DEBUG

#define dbg(...) cerr << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)

#else

#define dbg(...)

#endif





const int M = 2019;



int main() {

    ios::sync_with_stdio(false);

#ifndef NEAL_DEBUG

    cin.tie(nullptr);

#endif



    string S;

    cin >> S;

    vector<int64_t> dp(M, 0);

    int64_t ans = 0;



    for (char ch : S) {

        vector<int64_t> next_dp(M, 0);

        int value = ch - '0';

        next_dp[value]++;



        for (int m = 0; m < M; m++) {

            next_dp[value] += dp[m];

            value += 10;



            if (value >= M)

                value -= M;

        }



        dp = next_dp;

        ans += dp[0];

    }



    cout << ans << endl;

}


// Faster C++ solution for the same problem (measured speedup: 1.1858105234985172x):
#include <algorithm>

#include <cassert>

#include <iostream>

#include <vector>

using namespace std;



template<typename T> ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }

template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }



void dbg_out() { cerr << endl; }

template<typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cerr << ' ' << H; dbg_out(T...); }



#ifdef NEAL_DEBUG

#define dbg(...) cerr << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)

#else

#define dbg(...)

#endif





const int M = 2019;



int main() {

    ios::sync_with_stdio(false);

#ifndef NEAL_DEBUG

    cin.tie(nullptr);

#endif



    string S;

    cin >> S;

    int N = int(S.size());



    vector<int> freq(M, 0);

    freq[0] = 1;



    int value = 0, p10 = 1;

    int64_t total = 0;



    for (int i = N - 1; i >= 0; i--) {

        value = (value + p10 * (S[i] - '0')) % M;

        p10 = 10 * p10 % M;

        total += freq[value];

        freq[value]++;

    }



    cout << total << '\n';

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

using ll  = long long;

using vl  = vector<ll>;

using vvl = vector<vl>;



#define rep(i,n) for(int i = 0; i < (n); ++i)

#define per(i,n) for(int i = (n)-1; i >= 0; --i)

#define rng(i,a,b) for(int i = (a); i < (b); ++i)

#define all(a) (a).begin(), (a).end()

const int mod = 2019;



int main() {

    string s; cin >> s;

    reverse(all(s));

    ll base = 1, ans = 0;

    vl dp(2020,0);

    for (char c : s) {

        int x = c - '0';

        int num = (x * base) % mod;

        vl ndp(2020,0);

        per(i,2020) {

            if (dp[i] == 0) continue;

            ndp[(i+num)%mod] = dp[i];

        }

        ndp[num]++;

        ans += ndp[0];

        dp = ndp;

        (base *= 10) %= mod;

    }

    cout << ans << endl;

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.1922173483742382x):
#include <bits/stdc++.h>

using namespace std;

using ll  = long long;

using vl  = vector<ll>;

using vvl = vector<vl>;



#define rep(i,n) for(int i = 0; i < (n); ++i)

#define per(i,n) for(int i = (n)-1; i >= 0; --i)

#define rng(i,a,b) for(int i = (a); i < (b); ++i)

#define all(a) (a).begin(), (a).end()

const int mod = 2019;



int main() {

    string s; cin >> s;

    reverse(all(s));

    int n = s.size();



    ll ans = 0, base = 1, x = 0;

    map<ll,ll> cnts; cnts[0] = 1;

    rep(i,n) {

        x = (x + (s[i]-'0')*base) % mod;

        ans += cnts[x];

        cnts[x]++;

        (base *= 10) %= mod;

    }

    cout << ans << endl;

    return 0;

}
// Slower C++ solution:
// D.



#include <iostream>

#include <sstream>

#include <algorithm>

#include <vector>



using namespace std;

typedef long long LL;



int main(int argc, char* argv[]) {

	cout.precision(20);

#ifdef _MSC_VER

	while (true)

#endif

	{

		string s;

		cin >> s;

		if (s.empty()) return 0;

		LL ans = 0, sum = 0;

		vector<LL> dp(2020);

		dp[0] = 0;

		for (char c : s) {

			int d = c - '0';

			vector<LL> next(2020);

			for (int i = 0; i < 2019; ++i) {

				int x = (i * 10 + d) % 2019;

				next[x] += dp[i];

			}

			next[d] += 1;

			ans += next[0];

			dp = next;

		}

		cout << ans << endl;

	}

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.20891944210503x):
// D.



#include <iostream>

#include <sstream>

#include <algorithm>

#include <vector>



using namespace std;

typedef long long LL;

const LL MOD = 2019;



int main(int argc, char* argv[]) {

#ifdef _MSC_VER

	while (true)

#endif

	{

		string s;

		cin >> s;

		if (s.empty()) return 0;

		LL ans = 0, sum = 0;

		vector<LL> dp(MOD + 1);

		dp[0] = 1;

		LL d = 1, x = 0;

		// 桁DP

		for (auto it = s.rbegin(); it != s.rend(); ++it) {

			x = (x + d * (*it - '0')) % MOD;

			ans += dp[x];

			dp[x] += 1;

			d = (d * 10) % MOD;

		}

		cout << ans << endl;

	}

	return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;





int main() {

  string S;

  cin >> S;

  auto dp = vector< ll >(2019);

  ll ret = 0;

  for(auto &c : S) {

    auto dp2 = vector< ll >(2019);

    for(int i = 0; i < 2019; i++) {

      dp2[(i * 10 + (c - '0')) % 2019] += dp[i];

    }

    dp2[c - '0']++;

    ret += dp2[0];

    dp.swap(dp2);

  }

  cout << ret << endl;

}


// Faster C++ solution for the same problem (measured speedup: 1.1150386299809838x):
////D

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

int a[2019],ans;

 

int main() {

	ios::sync_with_stdio(false);

	cin.tie(0);

	string str;

	cin>>str;

	a[0]=1;

	ll t=0,cnt=1;

	for(int idx=str.length()-1;idx>=0;idx--){

		t=(t+cnt*(str[idx]-'0')%2019)%2019;

		//cout<<t<<endl;

		ans+=a[t];

		a[t]++;

		cnt=cnt*10%2019;

	}

	cout<<ans<<endl;

	return 0; 

}
// Slower C++ solution:
//codeforces

//

#include "bits/stdc++.h"

using namespace std;

int main(){

	char arr[200001];

	cin >> arr;



	long long int len = strlen(arr), nums[2020] = {1}, ans = 0;;

	int mods[len], dp[200005] = {0};;



	mods[len - 1] = 1, mods[len - 2] = 10;



	for(int i = len - 3; i >= 0; i--){

		mods[i] = (mods[i + 1] * 10) % 2019;

	}



	for(int i = len - 1; i >= 0; i--){

		dp[i] = (dp[i + 1] + ((arr[i] - '0') * mods[i])) % 2019;

		nums[dp[i]]++;

	}



	for(int i = 0; i < 2020; i++){

		ans += (nums[i] * (nums[i] - 1)) / 2;

	}



	cout << ans;

}


// Faster C++ solution for the same problem (measured speedup: 1.8176000454069257x):
//codeforces

//

#include "bits/stdc++.h"

using namespace std;

int main()

{

  string s;

  cin>>s;

  if(s.size()<4)

    cout<<0;

  else{

    int n=s.size();

    int arr[2200]={1};

    int mod[n+3]={0};

    mod[n-1]=1;

    mod[n-2]=10;

    for(int i=n-3; i>=0; i--)

      mod[i] = (mod[i+1]*10)%2019;

    int t=0;

    int p=0;

    for(int i=n-1; i>=0; i--){

      p = (p + (s[i]-'0')*mod[i])%2019;

      arr[p]++;

    }

    for(int i=0; i<2020; i++)

      t += (arr[i]*(arr[i]-1))/2;

    cout<<t;

  }

	return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

using ll=long long;

constexpr ll mod=1e9+7;



//return 10^n%2019

vector<int> vec(200030,1);



int main()

{

  for (auto i = 1; i < vec.size(); ++i)

  {

    vec[i]=(vec[i-1]*10)%2019;

  }



  string s;

  cin>>s;

  int n=s.size();

  vector<int> T(n,0);

  T[n-1]=(s[n-1]-'0')%2019;

  for (auto i = n-2; i >= 0; --i)

  {

    T[i]=((s[i]-'0')*vec[(n-i-1)]+T[i+1])%2019;

  }

  map<int,int> mp;

  for (auto i = 0; i < T.size(); ++i)

  {

    mp[T[i]]++;

  }

  mp[0]++;

  ll ans=0;

  for(const auto& e: mp) 

  {

    ans+=e.second*(e.second-1)/2;

  }

  cout<<ans<<endl;

}

// Faster C++ solution for the same problem (measured speedup: 2.744473417845868x):
#include<bits/stdc++.h>

using namespace std;

using ll=long long;

constexpr ll mod=1e9+7;



int main()

{



  string s;

  cin>>s;

  int n=s.size();

  int d=10;

  vector<int> T(n);

  T[n-1]=(s[n-1]-'0')%2019;

  for (int i = n-2; i >= 0; --i)

  {

    T[i]=((s[i]-'0')*d+T[i+1])%2019;

    d*=10;

    d%=2019;

  }

  map<int,int> mp;

  for (int i = 0; i < T.size(); ++i)

  {

    mp[T[i]]++;

  }

  mp[0]++;

  ll ans=0;

  for(const auto& e: mp) 

  {

    ans+=e.second*(e.second-1)/2;

  }

  cout<<ans<<endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>  // clang-format off

using Int = long long;

#define REP_(i, a_, b_, a, b, ...) for (Int i = (a), lim##i = (b); i < lim##i; i++)

#define REP(i, ...) REP_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)

struct SetupIO { SetupIO() { std::cin.tie(nullptr), std::ios::sync_with_stdio(false), std::cout << std::fixed << std::setprecision(13); } } setup_io;

#ifndef dump

#define dump(...)

#endif  // clang-format on



/**

 *    author:  knshnb

 *    created: Sun Apr 26 21:01:08 JST 2020

 **/



template <class T, class S> T make_vec(S x) { return x; }

template <class T, class... Ts> auto make_vec(size_t n, Ts... ts) {

    return std::vector<decltype(make_vec<T>(ts...))>(n, make_vec<T>(ts...));

}



const Int K = 2019;

signed main() {

    std::string s;

    std::cin >> s;

    Int n = s.size();

    auto dp = make_vec<Int>(2, K, 0);

    Int ans = 0;

    REP(i, n) {

        REP(j, K) {

            Int k = (10 * j + s[i] - '0') % K;

            dp[1][k] += dp[0][j];

        }

        dp[1][s[i] - '0'] += 1;

        ans += dp[1][0];

        std::swap(dp[0], dp[1]);

        std::fill(dp[1].begin(), dp[1].end(), 0);

    }

    std::cout << ans << std::endl;

}


// Faster C++ solution for the same problem (measured speedup: 1.1367398898238312x):
#include <bits/stdc++.h>  // clang-format off

using Int = long long;

#define REP_(i, a_, b_, a, b, ...) for (Int i = (a), lim##i = (b); i < lim##i; i++)

#define REP(i, ...) REP_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)

struct SetupIO { SetupIO() { std::cin.tie(nullptr), std::ios::sync_with_stdio(false), std::cout << std::fixed << std::setprecision(13); } } setup_io;

#ifndef dump

#define dump(...)

#endif  // clang-format on



/**

 *    author:  knshnb

 *    created: Tue Apr 28 20:35:37 JST 2020

 **/



const Int K = 2019;

signed main() {

    std::string s;

    std::cin >> s;

    Int n = s.size();

    std::vector<Int> cnt(K);

    cnt[0] = 1;

    Int pow = 1, cur = 0, ans = 0;

    for (Int i = n - 1; i >= 0; i--) {

        (cur += (s[i] - '0') * pow) %= K;

        (pow *= 10) %= K;

        ans += cnt[cur];

        cnt[cur]++;

    }

    std::cout << ans << std::endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define rep(i,n) for (int i = 0; i < (n); ++i)

#define all(v) v.begin(), v.end()

using namespace std;

typedef long long ll;



int main() {

	string s;

	cin >> s;

	ll ans = 0;

	int n = s.size();

	vector<ll> v(2020);

	rep(i, n) {

		int now = (int) (s[i] - '0');

		vector<ll> n = v;

		rep(j, 2019) {

			if(v[j] == 0) continue;

			ll next = (j*10 + now)%2019;

			n[next] += v[j];

			n[j] -= v[j];

			// if(i<5) cout << i << " " << j << " " << next << " " << v[next] << " " << v[j] << endl;

		}

		v = n;

		v[now]++;

		ans += v[0];

	}

	// rep(i, 2019) cout << i << " :" << v[i] << endl;

	cout << ans << endl;

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.3120630400230184x):
#include <bits/stdc++.h>

#define rep(i,n) for (int i = 0; i < (n); ++i)

#define all(v) v.begin(), v.end()

using namespace std;

typedef long long ll;



int main() {

	string s;

	cin >> s;

	reverse(all(s));

	ll ans = 0;

	int n = s.size();

	const int mod = 2019;

	vector<int> tot(n+1), cnt(mod);

	int x = 1;

	rep(i, n) {

		if(i == 0) tot[i+1] = (int) (s[i] - '0');

		else tot[i+1] = (tot[i] + (int) (s[i] - '0')* x) % mod;

		x *= 10;

		x %= mod;

	}

	rep(i, n+1) cnt[tot[i]]++;

	rep(i, mod) ans += cnt[i]*(cnt[i]-1)/2;

	// rep(i, n+1) cout << tot[i] << " ";

	cout << ans << endl;

	return 0;

}