cp-library

競技プログラミング用 C++ ライブラリ

View the Project on GitHub qandori/cp-library

:heavy_check_mark: 型を指定する階乗・逆階乗テーブル(軽量版)

components/factorial_table_light.hpp · GitHub で見る

64 KiBサイト · 軽量実装

軽量な二項係数の共通部品です。通常版 FPS を読み込まず、light_factorial_detail::Table<Mint>(max_n) で階乗・逆階乗を計算します。

素数法 \(p=\texttt{Mint::mod()}\) に対し、上限は \(N=\min(\texttt{max\_n},p-1)\) です。factorial[i]、inverse_factorial[i]、構築時の modulus を持ちます。max_n は非負で INT_MAX 未満にし、構築した表を使っている間は法を変更しません。

Mint は整数からの構築、乗算、mod() と inv() に対応する型を指定します。階乗は前から、逆階乗は末尾の逆元を 1 回だけ求めて後ろから生成します。

構築は \(O(N+\log p)\) 時間、\(O(N)\) 空間です。逆元計算を \(O(\log p)\) とします。

依存ライブラリ

検証コード

コード

#ifndef FACTORIAL_TABLE_LIGHT_HPP
#define FACTORIAL_TABLE_LIGHT_HPP

#include "../math/mint.hpp"
#include "factorial_table_generic.hpp"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <limits>
#include <type_traits>
#include <vector>

namespace light_factorial_detail {
template<class Mint> struct Table {
	decltype(Mint::mod()) modulus;
	std::vector<Mint> factorial, inverse_factorial;

	explicit Table(int max_n) : modulus(Mint::mod()) {
		assert(0 <= max_n && max_n < std::numeric_limits<int>::max() && modulus > 1);
		int n = static_cast<int>(std::min(std::uint64_t(max_n), std::uint64_t(modulus) - 1));
		factorial.resize(n + 1), inverse_factorial.resize(n + 1);
		factorial_table_detail::build<Mint, !std::is_same_v<Mint, mint>>(factorial.data(), inverse_factorial.data(), n);
	}
};
}

#endif
Back to top page