template<typename LowestPrime>
void sieve(int n, LowestPrime&& lowestPrime) {
std::vector<bool> isPrime(n + 1, true);
for (; i * i <= n; ++i) {
if (!isPrime[i]) continue;
for (auto j = static_cast<int64_t>(i) * i; j <= n; j += i) {
if (!isPrime[i]) continue;
template<typename LowestPrime>
void linearSieve(int n, LowestPrime&& lowestPrime) {
std::vector<int> lowestPrimes(n + 1, 0);
for (int i = 2; i <= n; ++i) {
for (auto const& p: primes) {
if (p > lowestPrimes[i]) break;
if (auto j = static_cast<int64_t>(i) * p; j <= n) {
std::vector<int> computeMobius(int n) {
std::vector<int> lowestPrimes(n + 1);
sieve(n, [&](int i, int lowestPrime) {
std::println("lowestPrimes[{}] = {}", i, lowestPrime);
lowestPrimes[i] = lowestPrime;
std::vector<int> mobius(n + 1);
for (int i = 2; i <= n; ++i) {
if (i == lowestPrimes[i]) {
} else if (int j = i / lowestPrimes[i]; lowestPrimes[j] != lowestPrimes[i]) {
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
auto mobius = computeMobius(n);
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;