stablegradients/pie-gem5-bysrc huggingface dataset:
// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



const int mxn = 2e5;



char s[mxn + 11];

int cnt[mxn + 11];



int main(){

	scanf("%s", s);

	int slen = strlen(s);

	int carry = 1;

	memset(cnt, 0, sizeof(cnt));

	cnt[0] = 1;

	int cur = 0;

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

		int digit = s[i] - '0';

		cur += digit * carry;

		cur %= 2019;

		cnt[cur]++;

		carry = carry * 10 % 2019;

	}

	int ans = 0;

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

		ans += (cnt[i] * (cnt[i] - 1) ) >> 1;

	}

	printf("%d\n", ans);

	return 0;

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 5, M = 3e3 + 5;

char s[N];

int cnt[M];

int main()

{

    int k = 1, sum = 0;

    scanf("%s", s);

    int len = strlen(s);

    for (int i = len - 1; ~i; --i)

    {

        sum = (sum + k * (s[i] - '0')) % 2019;

        ++cnt[sum];

        k = k * 10 % 2019;

    }

    ll ans = 0;

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

    {

        if (!i)

            ans += cnt[i];

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

    }

    printf("%lld\n", ans);

    return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

#define pi acos(-1)

#define ll long long

#define pii pair<ll,ll>

#define debug(a) cout<<a<<'\n'

#define maxn 100009 /// Still trying to be normal

#define MOD 1000000007

#define F first

#define S second

#define rep(i, a, b) for(ll i = a; i < (b); ++i)

#define per(i, b, a) for(ll i = b-1; i>=a ; i--)

#define trav(a, x) for(auto& a : x)

#define allin(a , x) for(auto a : x)

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

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

using namespace std;

const ll INF = 1e17 + 9;

int main(){

    ios::sync_with_stdio(false);

    cin.tie(0);

    string s;

    cin>>s;

    ll mod[2019];

    ll mod2[2019];

    memset(mod,0,sizeof mod);

    memset(mod2,0,sizeof mod2);

    mod[0]=1;

    ll num1=0,num2=0;

    ll ans=0;

    rep(i,0,sz(s)){

        rep(j,0,2019){

            int ant=mod[j];

            mod2[j*10%2019]+=ant;

        }

        rep(j,0,2019){

            mod[j]=mod2[j];

            mod2[j]=0;

        }

        num1=num1*10%2019;

        num1=(num1+(s[i]-'0'))%2019;

        // cout<<num1<<endl;

        ans+=mod[num1];

        mod[num1]++;

    }

    cout<<ans<<'\n';

    return 0;   

}

// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

#define pi acos(-1)

#define ll long long

#define pii pair<ll,ll>

#define debug(a) cout<<a<<'\n'

#define maxn 100009 /// Still trying to be normal

#define MOD 1000000007

#define F first

#define S second

#define rep(i, a, b) for(ll i = a; i < (b); ++i)

#define per(i, b, a) for(ll i = b-1; i>=a ; i--)

#define trav(a, x) for(auto& a : x)

#define allin(a , x) for(auto a : x)

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

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

using namespace std;

const ll INF = 1e17 + 9;

int main(){

    ios::sync_with_stdio(false);

    cin.tie(0);

    string s;

    cin>>s;

    ll mod[2019];

    memset(mod,0,sizeof mod);

    mod[0]=1;

    ll ant=0;

    ll ans=0;

    ll n = sz(s);

    ll base = 1;

    per(i,n,0){

        ll modact = (ant+(s[i]-'0')*base)%2019;

        ant=modact;

        // cout<<modact<<" "<<mod[modact]<<endl;

        ans+=mod[modact];

        base*=10;

        base%=2019;

        mod[modact]++;

    }

    cout<<ans<<'\n';

    return 0;   

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef pair<int,int>P;

const double eps = 1e-8;

const int NINF = 0xc0c0c0c0;

const int INF  = 0x3f3f3f3f;

const ll  mod  = 2019;

const ll  maxn = 1e6 + 5;

const int N = 2e5 + 5;



char s[N];

int a[N],pre[N],suf[N],n;



ll qpow(ll a,ll b){

	ll res=1;

	while(b>0){

		if(b&1) res=res*a%mod;

		a=a*a%mod;

		b>>=1;

	}

	return res;

}



map<ll,ll>M;



int main(){

	ios::sync_with_stdio(false);

	cin.tie(0);

	cin>>s+1;

	int n=strlen(s+1);

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

		a[i]=s[i]-'0';

	}

	int cnt=0;

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

	// 	pre[i]=(pre[i-1]*10+a[i])%mod;

	// 	if(pre[i]==0) cnt++;

	// }

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

		suf[i]=(suf[i+1]+a[i]*qpow(10,n-i+1))%mod;

		M[suf[i]]++;

	}

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

	// 	cout<<pre[i]<<"\n";

	// }

	M[0]++;

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

		if(M[i]>=2) cnt+=M[i]*(M[i]-1)/2;

	}

	// cout<<"\n\n\n";

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

		// cout<<suf[i]<<'\n';

	// }

	// for(int i=1;i)

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

	// 	if(pre[i]==0) 

	// }

	// cout<<(1+cnt)*cnt/2<<'\n';

	cout<<cnt<<'\n';

	return 0;

}

// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef pair<int,int>P;

const double eps = 1e-8;

const int NINF = 0xc0c0c0c0;

const int INF  = 0x3f3f3f3f;

const ll  mod  = 2019;

const ll  maxn = 1e6 + 5;

const int N = 2e5 + 5;



char s[N];

int a[N],suf[N],n,M[2020];



int main(){

	ios::sync_with_stdio(false);

	cin.tie(0);

	cin>>s+1;

	int n=strlen(s+1);

	int cnt=0;int base=1;

	M[0]++;

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

		a[i]=s[i]-'0';

		suf[i]=(suf[i+1]+a[i]*base)%mod;

		cnt+=M[suf[i]];

		M[suf[i]]++;

		base=base*10%mod;

	}

	cout<<cnt<<'\n';

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef pair<int,int>P;

const double eps = 1e-8;

const int NINF = 0xc0c0c0c0;

const int INF  = 0x3f3f3f3f;

const ll  mod  = 2019;

const ll  maxn = 1e6 + 5;

const int N = 2e5 + 5;



char s[N];

int a[N],suf[N],n;

map<ll,ll>M;



int main(){

	ios::sync_with_stdio(false);

	cin.tie(0);

	cin>>s+1;

	int n=strlen(s+1);

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

		a[i]=s[i]-'0';

	}

	int cnt=0;int base=1;

	M[0]++;

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

		suf[i]=(suf[i+1]+a[i]*base)%mod;

		M[suf[i]]++;

		base=base*10%mod;

	}

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

		if(M[i]>=2) cnt+=M[i]*(M[i]-1)/2;

	}

	cout<<cnt<<'\n';

	return 0;

}

// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef pair<int,int>P;

const double eps = 1e-8;

const int NINF = 0xc0c0c0c0;

const int INF  = 0x3f3f3f3f;

const ll  mod  = 2019;

const ll  maxn = 1e6 + 5;

const int N = 2e5 + 5;



char s[N];

int a[N],suf[N],n,M[2020];



int main(){

	ios::sync_with_stdio(false);

	cin.tie(0);

	cin>>s+1;

	int n=strlen(s+1);

	int cnt=0;int base=1;

	M[0]++;

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

		a[i]=s[i]-'0';

		suf[i]=(suf[i+1]+a[i]*base)%mod;

		cnt+=M[suf[i]];

		M[suf[i]]++;

		base=base*10%mod;

	}

	cout<<cnt<<'\n';

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <stdio.h>

using namespace std;

typedef long long ll;



int main(void) {

  ll i, j, n = 2019, now[n], tmp[n], ans = 0;

  char s[200010];

  scanf("%s", s);

  for(i = 0; i < n; ++i) now[i] = 0;

  now[0] = 1;

  for(i = 0; s[i]; ++i) {

    for(j = 0; j < n; ++j) tmp[j] = 0;

    for(j = 0; j < n; ++j) if(now[j]) tmp[(10 * j + s[i] - '0') % n] += now[j];

    ans += tmp[0];

    for(j = 0; j < n; ++j) now[j] = tmp[j];

    now[0]++;

  }

  printf("%lld", ans);

  return 0;

}

// Optimized solution to the same problem (faster):
#include <stdio.h>

using namespace std;

typedef long long ll;



int main(void) {

  ll i, j, n = 2019, m, cnt[n], ans = 0, now = 0;

  char s[200010];

  scanf("%s", s);

  for(i = 0; i < n; ++i) cnt[i] = 0;

  cnt[0] = 1;

  for(i = 0; s[i]; ++i);

  m = i;

  ll p[m];

  p[0] = 1;

  for(i = 1; i < m; ++i) p[i] = p[i - 1] * 10, p[i] %= n;

  for(i = m - 1; i >= 0; --i) {

    now += p[m - 1 - i] * (s[i] - '0'), now %= n;

    cnt[now]++;

  }

  for(i = 0; i < n; ++i) ans += cnt[i] * (cnt[i] - 1) / 2;

  printf("%lld", ans);

  return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}

// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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';

}


// Optimized solution to the same problem (faster):
#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();

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}

// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}

// Optimized solution to the same problem (faster):
#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;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}


// Optimized solution to the same problem (faster):
#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';

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}


// Optimized solution to the same problem (faster):
#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';

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}


// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
// 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;

}


// Optimized solution to the same problem (faster):
// 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;

}


// Fastest known solution for this problem: