C++ Library for Competitive Programming
#include "emthrm/math/mobius_mu_focusing_on_divisor.hpp"
$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)$ である。
が成り立つ。
時間計算量 | |
---|---|
$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}$) の数表 |
#ifndef EMTHRM_MATH_MOBIUS_MU_FOCUSING_ON_DIVISOR_HPP_
#define EMTHRM_MATH_MOBIUS_MU_FOCUSING_ON_DIVISOR_HPP_
#include <bit>
#include <map>
#include <vector>
namespace emthrm {
template <typename T>
std::map<T, int> mobius_mu_focusing_on_divisor(T n) {
std::vector<T> primes;
for (T i = 2; i * i <= n; ++i) {
if (n % i == 0) [[unlikely]] {
primes.emplace_back(i);
while (n % i == 0) n /= i;
}
}
if (n > 1) primes.emplace_back(n);
const int p = primes.size();
std::map<T, int> mu;
for (unsigned int i = 0; i < (1 << p); ++i) {
T d = 1;
for (int j = 0; j < p; ++j) {
if (i >> j & 1) d *= primes[j];
}
mu[d] = (std::popcount(i) & 1 ? -1 : 1);
}
return mu;
}
} // namespace emthrm
#endif // EMTHRM_MATH_MOBIUS_MU_FOCUSING_ON_DIVISOR_HPP_
#line 1 "include/emthrm/math/mobius_mu_focusing_on_divisor.hpp"
#include <bit>
#include <map>
#include <vector>
namespace emthrm {
template <typename T>
std::map<T, int> mobius_mu_focusing_on_divisor(T n) {
std::vector<T> primes;
for (T i = 2; i * i <= n; ++i) {
if (n % i == 0) [[unlikely]] {
primes.emplace_back(i);
while (n % i == 0) n /= i;
}
}
if (n > 1) primes.emplace_back(n);
const int p = primes.size();
std::map<T, int> mu;
for (unsigned int i = 0; i < (1 << p); ++i) {
T d = 1;
for (int j = 0; j < p; ++j) {
if (i >> j & 1) d *= primes[j];
}
mu[d] = (std::popcount(i) & 1 ? -1 : 1);
}
return mu;
}
} // namespace emthrm