CodeEff/ECCO huggingface dataset:
# Original solution
#import numpy as np
import sys, math
from itertools import permutations, combinations
from collections import defaultdict, Counter, deque
from math import factorial#, gcd
from bisect import bisect_left, bisect_right #bisect_left(list, value)
sys.setrecursionlimit(10**7)
enu = enumerate
MOD = 2019
def input(): return sys.stdin.readline()[:-1]
pl = lambda x: print(*x, sep='\n')

S = input()
N = len(S)

d = defaultdict(int)
d[0] += 1
# nums = [0]*(N+1)
last = 0
for i in range(N):
    m = 10**(N-i-1)%MOD
    # val = (int(S[i])*m + nums[i])%MOD
    val = (int(S[i])*m + last)%MOD
    last = val
    # cnt += d[val]
    d[val] += 1

cnt = 0
for i, v in d.items():
    cnt += v*(v-1)//2
print(cnt)


# Optimized solution
#import numpy as np
import sys, math
from itertools import permutations, combinations
from collections import defaultdict, Counter, deque
from math import factorial#, gcd
from bisect import bisect_left, bisect_right #bisect_left(list, value)
sys.setrecursionlimit(10**7)
enu = enumerate
MOD = 2019
def input(): return sys.stdin.readline()[:-1]
pl = lambda x: print(*x, sep='\n')

S = input()
N = len(S)

d = defaultdict(int)
d[0] += 1
# nums = [0]*(N+1)
m = 0
last = 0
dd = 1
for i in range(N):
    m += int(S[N-i-1])*dd
    m %= MOD
    # val = (int(S[i])*m + nums[i])%MOD
    # cnt += d[val]
    dd = (dd*10)%MOD
    d[m] += 1

cnt = 0
for i, v in d.items():
    cnt += v*(v-1)//2
print(cnt)
# Original solution
S = input()[::-1]
n = len(S)
dp = [0]*2019
dp[0] = 1
X = 0
Y = 1
for s in S:
    Z=(int(s)*Y)%2019
    X = (X+Z)%2019
    dp[X] += 1
    Y *= 10
answer = 0
for i in range(2019):
    answer += dp[i]*(dp[i]-1)/2
print((int(answer)))

# Optimized solution
S = input()[::-1]
n = len(S)
dp = [0]*2019
dp[0] = 1
X = 0
Y = 1
for s in S:
    Z=(int(s)*Y)%2019
    X = (X+Z)%2019
    dp[X] += 1
    Y = (10*Y)%2019
answer = 0
for i in range(2019):
    answer += dp[i]*(dp[i]-1)/2
print((int(answer)))
# Original solution
from collections import Counter
import sys
read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines

def main():
    S = readline().strip()[::-1]
    N = len(S)

    a = [0]
    s = 0
    for i in range(N):
        s += int(S[i]) * 10**i
        a.append(s % 2019)
    
    t = Counter(a)

    ans = 0
    for _, v in list(t.items()):
        ans += v * (v-1) // 2
    
    print(ans)
    

if __name__ == "__main__":
    main()


# Optimized solution
from collections import Counter
import sys
read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines

def main():
    S = readline().strip()[::-1]
    N = len(S)

    a = [0]
    s = 0
    for i in range(N):
        s += int(S[i]) * pow(10, i, 2019)
        a.append(s % 2019)
    
    t = Counter(a)

    ans = 0
    for _, v in list(t.items()):
        ans += v * (v-1) // 2
    
    print(ans)
    

if __name__ == "__main__":
    main()
# Original solution
import sys
## io
IS = lambda: sys.stdin.readline().rstrip()
II = lambda: int(IS())
MII = lambda: list(map(int, IS().split()))
MIIZ = lambda: list([x-1 for x in MII()])
## dp
INIT_VAL = 0
MD2 = lambda d1,d2: [[INIT_VAL]*d2 for _ in range(d1)]
MD3 = lambda d1,d2,d3: [MD2(d2,d3) for _ in range(d1)]
## math
DIVC = lambda x,y: -(-x//y)
DIVF = lambda x,y: x//y

def main():
    s = IS()
    n = len(s)
    cnt = 0
    for i in reversed(list(range(3,n))):
        if int(s[i-1])%2==0:
            if int(s[i])%2==0: pass
        for j in reversed(list(range(0,i-3))):
            if int(s[j:i+1])%2019 == 0:
                cnt += 1
    print(cnt)

if __name__ == '__main__':
    main()

# Optimized solution
import sys
## io
IS = lambda: sys.stdin.readline().rstrip()
II = lambda: int(IS())
MII = lambda: list(map(int, IS().split()))
MIIZ = lambda: list([x-1 for x in MII()])
## dp
INIT_VAL = 0
MD2 = lambda d1,d2: [[INIT_VAL]*d2 for _ in range(d1)]
MD3 = lambda d1,d2,d3: [MD2(d2,d3) for _ in range(d1)]
## math
DIVC = lambda x,y: -(-x//y)
DIVF = lambda x,y: x//y

def main():
    s = list(map(int, IS()))
    n = len(s)
    p = 2019
    cnt = 0
    d = [0]*p
    d[0] = 1 # 0(mod p)はそれ単体で割り切れるため+1しておく
    ss = 0
    x = 1
    for si in s[::-1]:
        ss += x*si
        ss %= p
        d[ss] += 1
        x = (10*x)%p # %p無しだとTLE
    cnt = 0
    for di in d:
        cnt += di*(di-1)//2 # calc combination(n_C_2)
    print(cnt)

if __name__ == '__main__':
    main()
# Original solution
s = input()[::-1]
d = 1
num = 0
ans = 0
mod_list = [0] * 2019
mod_list[0] = 1

for char in s:
    num += int(char) * d
    num %= 2019
    d *= 10
    d %= 2019
    mod_list[num % 2019] += 1

for i in range(2019):
    ans += mod_list[i] * (mod_list[i] - 1) //2

print(ans)


# Optimized solution
s = input()[::-1]
d = 1
num = 0
ans = 0
mod_list = [0] * 2019
mod_list[0] = 1

for char in s:
    num += int(char) * d
    mod_list[num % 2019] += 1
    d *= 10
    d %= 2019

for i in range(2019):
    ans += mod_list[i] * (mod_list[i] - 1) //2

print(ans)
# Original solution
import sys
from collections import defaultdict


s = str(eval(input()))
n = len(s)
p = 2019

a = []
t = 1
for i in range(n-1, -1, -1):
    a.append((ord(s[i])-ord("0")) * t % p)
    t = t * 10 % p
cum = [0]
for v in a:
    cum.append((cum[-1] + v) % p)

dic = defaultdict(int)
ans = 0
for v in cum:
    ans += dic[v]
    dic[v] += 1
print(ans)


# Optimized solution
import sys
from collections import defaultdict
def cnt_multiple(s, p):
    # ABC158E, ABC164D
    n = len(s)
    if p != 2 and p != 5:
        a = []
        t = 1
        for i in range(n-1, -1, -1):
            a.append((ord(s[i])-ord("0")) * t % p)
            t = t * 10 % p
        cum = [0]
        for v in a:
            cum.append((cum[-1] + v) % p)

        dic = defaultdict(int)
        ans = 0
        for v in cum:
            ans += dic[v]
            dic[v] += 1
        return ans
    elif p == 2:
        ans = 0
        for i in range(n):
            if (ord(s[i]) - ord("0")) % 2 == 0:
                ans += i+1
        return ans
    else:
        ans = 0
        for i in range(n):
            if (ord(s[i]) - ord("0")) % 5 == 0:
                ans += i+1
        return ans
s = str(eval(input()))
n = len(s)
p = 2019

print((cnt_multiple(s, p)))
# Original solution
S = input()[::-1]
 
## 余りを0~2018で総数保持
counts = [0]*2019
## 0桁の余りは0
counts[0] = 1
 
num, d = 0, 1
 
for c in S:
  ## 右から~桁の数字
  num += int(c) * d
  num %= 2019
  
  ## 次の桁
  d *= 10
  #d %= 2019
  
  counts[num] += 1
  
ans = 0
for cnt in counts:
  ## nC2の計算
  ans += cnt * (cnt-1) //2
  
print(ans)

# Optimized solution
S = input()[::-1]
 
## 余りを0~2018で総数保持
counts = [0]*2019
## 0桁の余りは0
counts[0] = 1
 
num, d = 0, 1
 
for c in S:
  ## 右から~桁の数字
  num += int(c) * d
  num %= 2019
  
  ## 次の桁
  d *= 10
  d %= 2019
  
  counts[num] += 1
  
ans = 0
for cnt in counts:
  ## nC2の計算
  ans += cnt * (cnt-1) //2
  
print(ans)
# Original solution
from sys import stdin


def get_result(data):
    S = data[0]
    int_S = int(S)
    mod_all_bit = [0] * 2019
    mod_all_bit[0] = 1
    for i in range(len(S)):
        mod = int_S % (10**(i+1)) % 2019
        mod_all_bit[mod] += 1
    ans = 0
    for val in mod_all_bit:
        if val >= 2:
            ans += val * (val-1) * 0.5
    return int(ans)


if __name__ == '__main__':
    data = list(map(str, stdin.readline().rstrip().split(' ')))
    result = get_result(data)
    print(result)


# Optimized solution
from sys import stdin


def get_result(data):
    S = data[0]
    mod_all_bit = [0] * 2019
    mod_all_bit[0] = 1
    # 10**i の mod を漸化式的に事前計算
    # こうすることで計算が効率化できる
    ten_i_mod = [0] * len(S)
    ten_i_mod[0] = 1
    for i in range(len(S)-1):
        ten_i_mod[i+1] = (ten_i_mod[i] * 10) % 2019
    mod = 0
    for i in range(len(S)):
        mod = (mod + ten_i_mod[i] * int(S[-(i+1)])) % 2019
        mod_all_bit[mod] += 1
    ans = 0
    for val in mod_all_bit:
        if val >= 2:
            ans += val * (val-1) * 0.5
    return int(ans)


if __name__ == '__main__':
    data = list(map(str, stdin.readline().rstrip().split(' ')))
    result = get_result(data)
    print(result)
# Original solution
s = input()[::-1]

cnts = [1] + [0] * (2019 - 1)
tmp = 0
d = 1

for i in s:
    tmp += int(i) * d
    cnts[tmp % 2019] += 1
    d *= 10

ans = 0
for cnt in cnts:
    ans += (cnt - 1) * cnt // 2

print(ans)

# Optimized solution
s = input()[::-1]

cnts = [1] + [0] * (2019 - 1)
tmp = 0
d = 1

for i in s:
    tmp += int(i) * d
    cnts[tmp % 2019] += 1
    d = d * 10 % 2019 # 桁数が大きくなりすぎる → 10と2019が素だから可能

ans = 0
for cnt in cnts:
    ans += (cnt - 1) * cnt // 2

print(ans)
# Original solution
from collections import Counter
S = input()[::-1]
cur = 0
mods = Counter()
mods[0] += 1
for i,d in enumerate(S):
  cur += int(d) * 10**i
  mods[cur%2019] += 1

res = 0
for k,v in list(mods.items()):
  res += (v * (v-1) // 2)

print(res)

# Optimized solution
from collections import Counter
S = input()[::-1]
cur = 0
mods = Counter()
mods[0] += 1
MOD = 2019
for i,d in enumerate(S):
  cur += int(d) * pow(10, i, MOD)
  mods[cur%MOD] += 1

res = 0
for k,v in list(mods.items()):
  res += (v * (v-1) // 2)

print(res)
# Original solution
p,*d,a,i=[1,1]+[0]*2020
for j in input()[::-1]:
  i=(i+int(j)*p)%2019
  a+=d[i]
  d[i]+=1
  p*=10
print(a)

# Optimized solution
M=2019
a=i=0
d=[1]+[0]*M
p=1
for j in input()[::-1]:
  i=(i+int(j)*p)%M
  a+=d[i]
  d[i]+=1
  p=p*10%M
print(a)
# Original solution
M=2019
a=i=0
d=[0]*M
p=1
for j in'0'+input()[::-1]:i=(i+int(j)*p)%M;p=p*10%M;a+=d[i];d[i]+=1
print(a)

# Optimized solution
M=2019
a=i=0
d=[0]*M
p=1
for j in input()[::-1]:d[i%M]+=1;i-=int(j)*p;a+=d[i%M];p=p*10%M
print(a)
# Original solution
S = str(eval(input()))
h = [int(x) for x in list(S)]
N = len(h)
a = [0] * 2019
a[0] = 1
T = 0
r = 1
c = 0
for i in range(N-1, -1, -1):
    T = T + h[i] * r
    q = T % 2019
    r = r * 10
    c += a[q]
    a[q] += 1
print(c)

# Optimized solution
S = str(eval(input()))
h = [int(x) for x in list(S)]
N = len(h)
a = [0] * 2019
a[0] = 1
T = 0
r = 1
c = 0
for i in range(N-1, -1, -1):
    T = (T + h[i] * r) % 2019
    r = r * 10
    r = r % 2019
    c += a[T]
    a[T] += 1
print(c)
# Original solution
number = str(eval(input()))
a = [number[i:j] for i in range(0, len(number)-1) for j in range(4, len(number)+1) if number[i:j] != '']
print((len([x for x in a if int(x)%2019==0])))  

# Optimized solution
number = str(eval(input()))
print((len([i for i in range(0, len(number)-1) for j in range(4, len(number)+1) if number[i:j] != '' and int(number[i:j])%2019==0])))
# Original solution
S = str(eval(input()))
s = len(S)
cnt = 0
A = [0]*2019
for i in range(s):
  x = int(S[i:])%2019
  A[x] += 1
for i in range(1,2019):
  if A[i] >= 2:
    cnt += A[i]*(A[i]-1)//2
cnt += A[0]*(A[0]+1)//2
print(cnt)

# Optimized solution
S = str(eval(input()))
s = len(S)
cnt = 0
A = [0]*2019
r = 0
for i in range(s):
  x = (r+pow(10, i, 2019)*int(S[s-i-1]))%2019
  A[x] += 1
  r = x
  
for i in range(1,2019):
  if A[i] >= 2:
    cnt += A[i]*(A[i]-1)//2
cnt += A[0]*(A[0]+1)//2

print(cnt)
# Original solution
s = input()[::-1]

dp = [0]*2019
dp[0]=1
total = 0
a = 1

for i in list(s):
  total += (int(i)*a)%2019
  dp[total%2019] += 1
  a *= 10
count=0
  
for i in range(2019):
    count += dp[i]*(dp[i]-1)//2
 
print(count)

# Optimized solution
s = input()[::-1]

dp = [0]*2019
dp[0]=1
total = 0
a = 1

for i in list(s):
  total += int(i)*a
  total %= 2019
  dp[total] += 1
  a *= 10
  a %= 2019
count=0
  
for i in range(2019):
    count += dp[i]*(dp[i]-1)//2
 
print(count)
# Original solution
S = str(eval(input()))
N = len(S)
ans1 = [0] * 2019
ans2 = 0

T = [0] *  (N + 1)
T[N] = 0
ans1[0] += 1

for i in range(N - 1, -1, -1):
  #print(i)
  T[i] = (T[i + 1] + 10 ** (N - i - 1) * int(S[i])) % 2019
  ans1[T[i]] += 1

for i in range(2019):
  x = ans1[i]
  ans2 += x * (x - 1) / 2
  
#print(ans1[0])
#print(T)
print((int(ans2)))  



# Optimized solution
S = str(eval(input()))
N = len(S)
ans1 = [0] * 2019
ans2 = 0

T = [0] *  (N + 1)
T[N] = 0
ans1[0] += 1

P = 1
for i in range(N - 1, -1, -1):
  #print(i)
  T[i] = (T[i + 1] + P * int(S[i])) % 2019
  ans1[T[i]] += 1
  P = 10 * P % 2019

for i in range(2019):
  x = ans1[i]
  ans2 += x * (x - 1) / 2
  
#print(ans1[0])
#print(T)
print((int(ans2)))
# Original solution
s = input()[::-1]

dataset = [0]*2019
dataset[0] = 1

n = 0
d = 0

for i in s:
    n += int(i) * (10**d)
    a = n % 2019
    dataset[a] += 1
    d += 1

count = 0
for i in dataset:
    count += i * (i-1) // 2

print(count)

# Optimized solution
s = input()[::-1]

dataset = [0]*2019
dataset[0] = 1

n = 0
d = 1

for i in s:
    n += int(i) * d
    a = n % 2019
    dataset[a] += 1
    d *= 10
    d %= 2019

count = 0
for i in dataset:
    count += i * (i-1) // 2

print(count)
# Original solution
from collections import Counter
def main():
    mod=2019
    S=input().strip()
    l=len(S)
    M=[0]*(l+1)
    p=1
    for i in range(1,l+1):
        x=int(S[l-i])
        M[i]=(M[i-1]+x*p)%mod
        p*=10
    C=Counter(M)
    ans=0
    for m in list(C.values()):
        ans+=m*(m-1)//2
    print(ans)
    
if __name__=='__main__':
    main()

# Optimized solution
from collections import Counter
def main():
    mod=2019
    S=input().strip()
    l=len(S)
    M=[0]*(l+1)
    p=1
    for i in range(1,l+1):
        x=int(S[l-i])
        M[i]=(M[i-1]+x*p)%mod
        p*=10
        p%=mod
    C=Counter(M)
    ans=0
    for m in list(C.values()):
        ans+=m*(m-1)//2
    print(ans)
    
if __name__=='__main__':
    main()
# Original solution
s = input()[::-1]
l = len(s)
MOD = 2019
ans = 0
mods = [0] * 2019
mods[0] = 1
num = 0
cnt = 0
for i in s:
    num += int(i) * (10**cnt)
    num %= MOD
    mods[num] += 1
    cnt += 1

for j in mods:
    ans += int(j*(j-1)/2)

print(ans)


# Optimized solution
s = input()[::-1]
l = len(s)
MOD = 2019
ans = 0
mods = [0] * 2019
mods[0] = 1
num = 0
cnt = 0
d = 1
for i in s:
    num += int(i) * d
    num %= MOD
    mods[num] += 1
    d *= 10
    d %= MOD

for j in mods:
    ans += int(j*(j-1)/2)

print(ans)
# Original solution
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
from collections import defaultdict 
def main():
    s = readline().rstrip().decode()
    n = len(s)
    T = [0]
    P = 2019
    dd = defaultdict(int)
    dd[0] += 1
    for i in range(1, n+1):
        v = ((ord(s[-i])-ord('0'))*10**(i-1) + T[i-1])%P
        dd[v] += 1
        T.append(v)
    ans = 0
    for v in list(dd.values()):
        ans += v*(v-1)//2
    print(ans)
if __name__ == '__main__':
    main()


# Optimized solution
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
from collections import defaultdict 
def main():
    s = readline().rstrip().decode()
    n = len(s)
    T = [0]
    P = 2019
    dd = defaultdict(int)
    dd[0] += 1
    for i in range(1, n+1):
        v = ((ord(s[-i])-ord('0'))*pow(10, i-1, P) + T[i-1])%P
        dd[v] += 1
        T.append(v)
    ans = 0
    for v in list(dd.values()):
        ans += v*(v-1)//2
    print(ans)
if __name__ == '__main__':
    main()
# Original solution
S = input()[::-1]
Surpus = [0] * 2019
Surpus[0] = 1

sum = 0
x = 1
for i in S:
    sum += int(i) * x
    Surpus[sum % 2019] += 1
    x *= 10

ans = 0
for i in Surpus:
    ans += i * (i - 1) // 2

print(ans)

# Optimized solution
S = input()[::-1]
Surpus = [0] * 2019
Surpus[0] = 1

sum = 0
x = 1
for i in S:
    sum += int(i) * x
    Surpus[sum % 2019] += 1
    x *= 10
    x %= 2019

ans = 0
for i in Surpus:
    ans += i * (i - 1) // 2

print(ans)
# Original solution
S=input()[::-1]
l=len(S)
t=0
p=0

ss=[0]*2019
ss[0]=1
d=1
for i in S:
    p=(p+int(i)*d)%2019
    d*=10
    ss[p]+=1

for c in ss:
    t+=c*(c-1)//2
print(t)


# Optimized solution

S=input()[::-1]
l=len(S)
t=0
p=0

ss=[0]*2019
ss[0]=1
d=1
for i in S:
    p=(p+int(i)*d)%2019
    d*=10
    d%=2019
    ss[p]+=1

for c in ss:
    t+=c*(c-1)//2
print(t)
# Original solution
#!/usr/bin/env python3
# n,m = map(int,sys.stdin.readline().split())
# a = list(map(int,sys.stdin.readline().split()))
# a = [sys.stdin.readline() for _ in range(n)]
# s = sys.stdin.readline().rstrip()
# n = int(sys.stdin.readline())
import sys,bisect,math
sys.setrecursionlimit(15000)

s = sys.stdin.readline().rstrip()
cum = [0]*(len(s)+1)#cumulative sum
import collections
d = collections.defaultdict(list)
for i in range(len(s)):
    cum[i+1]=cum[i]+int(s[i])
for i in range(len(s)+1):
    d[cum[i]%3].append(i)
ret = 0
#print(cum,d)
for l in list(d.values()):
    #print(l)
    n = len(l)
    can = [[l[i],l[j]] for i in range(n) for j in range(i,n) if l[j] > l[i]+3]
    #print(can)
    #print([[i,j,int(s[i:j])] for i,j in can if int(s[i:j])>2019 and int(s[i:j])%2019==0])
    #print([1 for i,j in can if int(s[i:j])>2019 and int(s[i:j])%2019==0])
    ret += sum(1 for i,j in can if int(s[i:j])>2019 and math.gcd(int(s[i:j]),2019)==2019)
print(ret)


# Optimized solution
#!/usr/bin/env python3
# n,m = map(int,sys.stdin.readline().split())
# a = list(map(int,sys.stdin.readline().split()))
# a = [sys.stdin.readline() for _ in range(n)]
# s = sys.stdin.readline().rstrip()
# n = int(sys.stdin.readline())
import sys,bisect,math
sys.setrecursionlimit(15000)

s = sys.stdin.readline().rstrip()
cum = [0]*(len(s)+1)#cumulative sum
import collections
d = collections.defaultdict(int)
d[0] = 1
ret = 0
for i in range(len(s))[::-1]:
    cum[i+1]=int(s[i:])%2019
    if cum[i+1] in d:
        ret += d[cum[i+1]]
    d[cum[i+1]] += 1
#print(d,cum,ret)
print(ret)
# Original solution
s = str(eval(input()))
N = len(s)
array = [0]*2019
array[0] += 1
count = 0
d = 0
for i in reversed(list(range(0, N))):
    x = s[i:N]
    y = int(x)
    d = ( d + int( s[i] ) * 10 ** ( N - i - 1 ) % 2019 ) % 2019
    array[d] += 1
for i in array:
    count += i*(i-1)/2
print((int(count)))

# Optimized solution
s = str(eval(input()))
N = len(s)
array = [0]*2019
array[0] += 1
count = 0
d = 1
r = 0
for i in reversed(list(range(0, N))):
    #x = s[i:N]
    #y = int(x)
    r = ( r + int( s[i] ) * d ) % 2019
    d = d * 10 % 2019
    array[r] += 1
for i in array:
    count += i*(i-1)/2
print((int(count)))
# Original solution
import itertools

S = input()[::-1]

m = [0]*len(S)
tmp = 1
for i in range(len(S)):
    m[i] = int(S[i])*tmp%2019
    tmp *= 10

cum = [0]+[0]*len(S)
for i in range(1,len(S)+1):
    cum[i] = (cum[i-1]+m[i-1])%2019

d = {}
ans = 0
for i in range(len(cum)):
    if cum[i] not in d:
        d[cum[i]] = 1
    else:
        ans += d[cum[i]]
        d[cum[i]] += 1
print(ans)

# Optimized solution
import itertools

S = input()[::-1]

m = [0]*len(S)
tmp = 1
for i in range(len(S)):
    m[i] = int(S[i])*tmp%2019
    tmp = tmp*10%2019

cum = [0]+[0]*len(S)
for i in range(1,len(S)+1):
    cum[i] = (cum[i-1]+m[i-1])%2019

d = {}
ans = 0
for i in range(len(cum)):
    if cum[i] not in d:
        d[cum[i]] = 1
    else:
        ans += d[cum[i]]
        d[cum[i]] += 1
print(ans)
# Original solution
s = input()[::-1]

sum_of_digits = 0

cnts = [0] * 2019
cnts[0] = 1

d = 1

for c in s:
    sum_of_digits += int(c) * d
    sum_of_digits %= 2019
    d *= 10
    d % 2019
    cnts[sum_of_digits] += 1

ans = 0

for cnt in cnts:
    ans += cnt * (cnt - 1) // 2
 
print(ans)

# Optimized solution
s = input()[::-1]

sum_of_digits = 0

cnts = [0] * 2019
cnts[0] = 1

d = 1

for c in s:
    sum_of_digits += int(c) * d
    sum_of_digits %= 2019
    d *= 10
    d %= 2019
    cnts[sum_of_digits] += 1

ans = 0

for cnt in cnts:
    ans += cnt * (cnt - 1) // 2
 
print(ans)
# Original solution
#MLE注意！ not は使わず !=
#0や1のケースに注意

def main():
    import sys
    input = sys.stdin.readline
    sys.setrecursionlimit(10**7)
    from collections import Counter, deque
    #from collections import defaultdict
    from itertools import combinations, permutations, accumulate, groupby, product
    from bisect import bisect_left,bisect_right
    from heapq import heapify, heappop, heappush
    import math

    #inf = 10**17
    #mod = 10**9 + 7

    n = input().rstrip()
    n = n[::-1]
    res = [0]*2019
    res[0] += 1
    b = 0
    for i in range(len(n)):
        a = int(n[i])
        b += a*(10**i)%2019
        b %= 2019
        res[b] += 1
    ans = 0
    for i in res:
        if i>=2:
            ans += i*(i-1)//2
    print(ans)

if __name__ == '__main__':
    main()

# Optimized solution
#MLE注意！ not は使わず !=
#0や1のケースに注意

def main():
    import sys
    input = sys.stdin.readline
    sys.setrecursionlimit(10**7)
    from collections import Counter, deque
    #from collections import defaultdict
    from itertools import combinations, permutations, accumulate, groupby, product
    from bisect import bisect_left,bisect_right
    from heapq import heapify, heappop, heappush
    import math

    #inf = 10**17
    #mod = 10**9 + 7

    n = input().rstrip()
    n = n[::-1]
    res = [0]*2019
    res[0] += 1
    b = 1
    c = 0
    for i in range(len(n)):
        a = int(n[i])
        c += a*b
        c %= 2019
        res[c] += 1
        b = b*10%2019
    ans = 0
    for i in res:
        if i>=2:
            ans += i*(i-1)//2
    print(ans)

if __name__ == '__main__':
    main()
# Original solution
s=str(eval(input()))
n=len(s)
ans=0
l=[0 for i in range(2019)]
for i in range(n):
  t=int(s[i:])
  l[t%2019]+=1
#print(l[1817])
ans+=l[0]
l[0]=0
for i in l:
  ans+=int(i*(i-1)//2)
print(ans)

# Optimized solution
s=str(eval(input()))
n=len(s)
ans=0
l=[0 for i in range(2019)]
now=l[int(s[n-1])]
r=1
for i in range(1,n+1):
  now=(now+int(s[-i])*r)%2019
  l[now]+=1
  r=r*10
  r=r%2019
ans+=l[0]
for i in l:
  ans+=int(i*(i-1)//2)
print(ans)
#print(l)
# Original solution
s = input()[::-1]

counts = [0] * 2019
counts[0] = 1

num, d = 0, 1

for char in s:
    num += int(char) * d
    num %= 2019
    counts[num] += 1
    d *= 10

ans = 0
for cnt in counts:
    ans += cnt * (cnt - 1) // 2
    
print(ans)

# Optimized solution
s = input()[::-1] # 入力文字列を逆順でsに格納

counts = [0] * 2019
counts[0] = 1

num, d = 0, 1

for char in s:
    num += int(char) * d
    num %= 2019
    d *= 10
    d%= 2019
    counts[num] += 1

ans = 0
for cnt in counts:
    ans += cnt * (cnt - 1) // 2

print(ans) # 答えの出力
# Original solution
#!/usr/bin/env python3
import sys


def solve(S: str):

    l = [0] * 2019
    ps = 0
    d = 1
    for i in range(1, len(S) + 1):
        ps += int(S[-i]) * d
        l[ ps % 2019 ] += 1
        d *= 10

    ans = 0
    for i in l:
        ans += i * (i - 1) // 2
    
    ans += l[0]
    
    print(ans)

    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    S = next(tokens)  # type: str
    solve(S)

if __name__ == '__main__':
    main()


# Optimized solution
#!/usr/bin/env python3
import sys


def solve(S: str):

    l = [0] * 2019
    ps = 0
    d = 1
    for i in range(1, len(S) + 1):
        ps += int(S[-i]) * d
        l[ ps % 2019 ] += 1
        d = d * 10 % 2019

    ans = 0
    for i in l:
        ans += i * (i - 1) // 2
    
    ans += l[0]
    
    print(ans)

    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    S = next(tokens)  # type: str
    solve(S)

if __name__ == '__main__':
    main()
# Original solution
from collections import Counter
s=input()[::-1]
m=len(s)
DP=[0]
word=""

for i in s:
    word=i+word
    DP.append(int(word)%2019)

DP=Counter(DP)
ans=0
for v,m in list(DP.items()):
    if m>=2:
        ans +=m*(m-1)//2
print(ans)

# Optimized solution
from collections import Counter
s=input()[::-1]
DP=[0]

num,point=0,1
for i in s:
    num +=int(i)*point
    num %=2019
    DP.append(num)
    point *=10
    point %=2019

ans=0
DP=Counter(DP)
for v,m in list(DP.items()):
    if m>=2:
        ans +=m*(m-1)//2
print(ans)