from concurrent.futures import ThreadPoolExecutor
from time import perf_counter

def work(start, stop):
    s = 0
    for i in range(start, stop):
        s += (i*i) % 97
    return s

def threaded(n, nthreads):
    block = n // nthreads

    ranges = [
        (i*block, (i+1)*block if i < nthreads-1 else n)
        for i in range(nthreads)
    ]

    t0 = perf_counter()

    with ThreadPoolExecutor(max_workers=nthreads) as pool:
        result = sum(pool.map(lambda r: work(*r), ranges))

    return perf_counter() - t0, result

N = 50_000_000

for nt in [1, 2, 4]:
    t, result = threaded(N, nt)
    print(f"{nt} {t:.3f}")
