cp-library

C++ Library for Competitive Programming

View the Project on GitHub emthrm/cp-library

:question: メビウス関数 (Möbius function) の数表
(include/emthrm/math/mobius_mu_init.hpp)

メビウス関数 (Möbius function)

$n \in \mathbb{N}^+$ に対して

\[\mu(n) \mathrel{:=} \begin{cases} 0 & (\exists p \in \mathbb{P},\ n \equiv 0 \pmod{p^2}), \\ (-1)^{\# \lbrace \text{相異なる素因数} \rbrace} & (\text{otherwise}) \end{cases}\]

で定義される $\mu(n)$ である。

が成り立つ。

メビウスの反転公式 (Möbius inversion formula)

\[f(n) = \sum_{d \mid n} g(d) \implies g(n) = \sum_{d \mid n} \mu \left(\frac{n}{d} \right) f(d) = \sum_{d \mid n} \mu(d) f \left(\frac{n}{d} \right)\]

時間計算量

  時間計算量
  $O(\sqrt{N})$
約数版  
数表 $O(N\log{\log{N}})$
数表2 $O\left(\sqrt{H}\log{\log{H}} + \frac{(H - L)\sqrt{H}}{\log{H}}\right)$ ?

仕様

名前 戻り値
int mobius_mu(long long n); $\mu(n)$

約数版

名前 戻り値 備考
template <typename T>
std::map<T, int> mobius_mu_focusing_on_divisor(T n);
$\lbrace n \text{ の約数 } d, \mu(d) \rbrace$ キーとして存在しないときは値 $0$ である。

数表

名前 戻り値
std::vector<int> mobius_mu_init(const int n); メビウス関数 $\mu(i)$ ($1 \leq i \leq n$) の数表
std::vector<int> mobius_mu_init2(const long long low, const long long high); メビウス関数 $\mu(i)$ ($\mathrm{low} \leq i < \mathrm{high}$) の数表

参考文献

TODO

Submissons

Verified with

Code

#ifndef EMTHRM_MATH_MOBIUS_MU_INIT_HPP_
#define EMTHRM_MATH_MOBIUS_MU_INIT_HPP_

#include <vector>

namespace emthrm {

std::vector<int> mobius_mu_init(const int n) {
  std::vector<bool> is_prime(n + 1, true);
  is_prime[0] = false;
  if (n >= 1) [[likely]] is_prime[1] = false;
  std::vector<int> mu(n + 1, 1);
  mu[0] = 0;
  for (int i = 2; i <= n; ++i) {
    if (is_prime[i]) [[unlikely]] {
      mu[i] = -mu[i];
      for (int j = i * 2; j <= n; j += i) {
        is_prime[j] = false;
        mu[j] = ((j / i) % i == 0 ? 0 : -mu[j]);
      }
    }
  }
  return mu;
}

}  // namespace emthrm

#endif  // EMTHRM_MATH_MOBIUS_MU_INIT_HPP_
#line 1 "include/emthrm/math/mobius_mu_init.hpp"



#include <vector>

namespace emthrm {

std::vector<int> mobius_mu_init(const int n) {
  std::vector<bool> is_prime(n + 1, true);
  is_prime[0] = false;
  if (n >= 1) [[likely]] is_prime[1] = false;
  std::vector<int> mu(n + 1, 1);
  mu[0] = 0;
  for (int i = 2; i <= n; ++i) {
    if (is_prime[i]) [[unlikely]] {
      mu[i] = -mu[i];
      for (int j = i * 2; j <= n; j += i) {
        is_prime[j] = false;
        mu[j] = ((j / i) % i == 0 ? 0 : -mu[j]);
      }
    }
  }
  return mu;
}

}  // namespace emthrm
Back to top page