Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub ebi-fly13/Library

:heavy_check_mark: Multiple Transform (Zeta / Möbius)
(math/multiple_transform.hpp)

説明

倍数に対してゼータ変換とメビウス変換を行う。 $O(N\log \log N)$

Depends on

Required by

Verified with

Code

#pragma once

#include <vector>

#include "../math/eratosthenes_sieve.hpp"

namespace ebi {

struct multiple_transform {
    multiple_transform() = default;

    template <class mint>
    static std::vector<mint> zeta_transform(const std::vector<mint> &f) {
        int n = f.size() - 1;
        auto F = f;
        if (m < n) {
            while (m < n) m <<= 1;
            eratosthenes_sieve sieve(m);
            primes = sieve.prime_table();
        }
        for (const auto &p : primes) {
            if (n < p) break;
            for (int i = n / p; i > 0; i--) F[i] += F[i * p];
        }
        return F;
    }

    template <class mint>
    static std::vector<mint> mobius_transform(const std::vector<mint> &F) {
        int n = F.size() - 1;
        auto f = F;
        if (m < n) {
            while (m < n) m <<= 1;
            eratosthenes_sieve sieve(m);
            primes = sieve.prime_table();
        }
        for (const auto &p : primes) {
            if (n < p) break;
            for (int i = 1; i * p <= n; i++) f[i] -= f[i * p];
        }
        return f;
    }

  private:
    static int m;
    static std::vector<int> primes;
};

int multiple_transform::m = 4;
std::vector<int> multiple_transform::primes = {2, 3};

}  // namespace ebi
#line 2 "math/multiple_transform.hpp"

#include <vector>

#line 2 "math/eratosthenes_sieve.hpp"

#include <cassert>

#include <cstdint>

#line 6 "math/eratosthenes_sieve.hpp"

/*
    reference: https://37zigen.com/sieve-eratosthenes/
*/

namespace ebi {

struct eratosthenes_sieve {
  private:
    using i64 = std::int_fast64_t;
    int n;
    std::vector<bool> table;

  public:
    eratosthenes_sieve(int _n) : n(_n), table(std::vector<bool>(n + 1, true)) {
        table[1] = false;
        for (i64 i = 2; i * i <= n; i++) {
            if (!table[i]) continue;
            for (i64 j = i; i * j <= n; j++) {
                table[i * j] = false;
            }
        }
    }

    bool is_prime(int p) {
        return table[p];
    }

    std::vector<int> prime_table(int m = -1) {
        if (m < 0) m = n;
        std::vector<int> prime;
        for (int i = 2; i <= m; i++) {
            if (table[i]) prime.emplace_back(i);
        }
        return prime;
    }
};

}  // namespace ebi
#line 6 "math/multiple_transform.hpp"

namespace ebi {

struct multiple_transform {
    multiple_transform() = default;

    template <class mint>
    static std::vector<mint> zeta_transform(const std::vector<mint> &f) {
        int n = f.size() - 1;
        auto F = f;
        if (m < n) {
            while (m < n) m <<= 1;
            eratosthenes_sieve sieve(m);
            primes = sieve.prime_table();
        }
        for (const auto &p : primes) {
            if (n < p) break;
            for (int i = n / p; i > 0; i--) F[i] += F[i * p];
        }
        return F;
    }

    template <class mint>
    static std::vector<mint> mobius_transform(const std::vector<mint> &F) {
        int n = F.size() - 1;
        auto f = F;
        if (m < n) {
            while (m < n) m <<= 1;
            eratosthenes_sieve sieve(m);
            primes = sieve.prime_table();
        }
        for (const auto &p : primes) {
            if (n < p) break;
            for (int i = 1; i * p <= n; i++) f[i] -= f[i * p];
        }
        return f;
    }

  private:
    static int m;
    static std::vector<int> primes;
};

int multiple_transform::m = 4;
std::vector<int> multiple_transform::primes = {2, 3};

}  // namespace ebi
Back to top page