分割数を $p(0)$ から $p(n)$ まで列挙する
lib/combinatorics/partition_function.hpp
概要
生成関数 $\prod_{k\ge1}(1-x^k)^{-1}$ の分母を五角数定理で構築し、 形式的冪級数の逆元を求める。
インクルード
#include "combinatorics/partition_function.hpp"
関数
| 名前 | 説明 |
|---|---|
partition_function |
分割数を $p(0)$ から $p(n)$ まで列挙する |
検証
依存するヘッダ(11)
-
二項係数・階乗・順列・多項係数・重複組合せ
lib/combinatorics/combinatorics.hpp -
形式的冪級数 (FPS)
lib/convolution/formal_power_series.hpp -
NTT・畳み込み (convolution)
lib/convolution/ntt.hpp -
Montgomery + AVX2 による NTT 畳み込み (NTT-friendly な 32bit 素数 mod 専用)
lib/convolution/ntt_avx2.hpp -
internal/internal_fft.hpp
lib/internal/internal_fft.hpp -
internal/internal_fft_avx2.hpp
lib/internal/internal_fft_avx2.hpp -
internal/internal_fps_avx2.hpp
lib/internal/internal_fps_avx2.hpp -
internal/internal_math.hpp
lib/internal/internal_math.hpp -
internal/internal_type_traits.hpp
lib/internal/internal_type_traits.hpp -
modint (static_modint / dynamic_modint)
lib/number_theory/modint.hpp -
素数法上で `x` の平方根を 1 つ返す
lib/number_theory/root_mod.hpp
検証プログラム(1)
-
test/yosupo/enumerative_conbinatorics/partition_function.test.cpp
test/yosupo/enumerative_conbinatorics/partition_function.test.cpp
実装
#pragma once
#include <vector>
#include "convolution/formal_power_series.hpp"
#include "number_theory/modint.hpp"
/// @brief 分割数を $p(0)$ から $p(n)$ まで列挙する
/// @details 生成関数 $\prod_{k\ge1}(1-x^k)^{-1}$ の分母を五角数定理で構築し、
/// 形式的冪級数の逆元を求める。
/// @tparam mint NTTを利用できる static modint 型
/// @param n 求める最大の添字。0以上であること
/// @return 長さ $n+1$ の列。i番目の要素は分割数 $p(i)$
/// @complexity $O(n\log n)$
template <internal::static_modint_c mint>
std::vector<mint> partition_function(int n) {
std::vector<mint> den(n + 1);
den[0] = 1;
// 一般五角数 g = k(3k-1)/2 (k = 1, -1, 2, -2, ...) について
// 係数 (-1)^k を立てる。符号は 2 個ごとに反転する。
for (int k = 1;; ++k) {
long long g1 = (long long)k * (3 * k - 1) / 2;
long long g2 = (long long)k * (3 * k + 1) / 2;
if (g1 > n) break;
mint sign = (k & 1) ? mint(-1) : mint(1);
den[g1] += sign;
if (g2 <= n) den[g2] += sign;
}
return fps::inv(den, n + 1);
}