This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "math/binomial.hpp"二項係数を前計算する
Binomial<T>(unsigned n)
逆元の計算を$O(\log{M})$,その他の演算を$O(1)$として
T p(int a, int b)
順列の総数${}_a P_b$を返す
T c(int a, int b)
組み合わせの総数${}_a C_b$を返す
T h(int a, int b)
重複組み合わせの総数${}_a H_b$を返す
#pragma once
#include "../template/template.hpp"
/**
* @brief Binomial (二項係数)
* @note 参考: https://blog.hamayanhamayan.com/entry/2018/06/06/210256
*/
template <class T>
class Binomial {
private:
int n;
vector<T> fact, ifact;
public:
Binomial() : Binomial(0) {}
Binomial(int _n) : n(_n), fact(_n + 1), ifact(_n + 1) {
assert(0 <= _n);
fact[0] = T(1);
rep (i, 0, n) {
fact[i + 1] = fact[i] * T(i + 1);
}
ifact[n] = T(1) / fact[n];
rrep (i, n, 1) {
ifact[i - 1] = ifact[i] * T(i);
}
}
//! 順列
T p(int a, int b) const {
if (b < 0 || a < b) {
return T(0);
}
assert(0 <= a && a <= n);
assert(0 <= a - b && a - b <= n);
return fact[a] * ifact[a - b];
}
//! 組合せ
T c(int a, int b) const {
if (b < 0 || a < b) {
return T(0);
}
assert(0 <= b && b <= n);
return p(a, b) * ifact[b];
}
//! 重複組合せ
T h(int a, int b) const {
if (a == 0 && b == 0) {
return T(1);
}
if (a <= 0 || b < 0) {
return T(0);
}
return c(a + b - 1, b);
}
};
#line 2 "math/binomial.hpp"
#line 2 "template/template.hpp"
/**
* @author ku_senjan
* @title 提出用テンプレート
* @see https://github.com/kogetsu0728/ku-library
*/
#line 2 "template/constant.hpp"
#line 2 "template/include.hpp"
#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
using namespace std;
#line 2 "template/type_alias.hpp"
#line 4 "template/type_alias.hpp"
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
template <class T, bool REVERSE = false>
using heap = priority_queue<T, vector<T>, conditional_t<REVERSE, greater<T>, less<T>>>;
#line 5 "template/constant.hpp"
template <class T>
inline constexpr T INF = numeric_limits<T>::max() / 2;
inline constexpr array<int, 4> DY4 = {0, -1, 0, 1};
inline constexpr array<int, 4> DX4 = {1, 0, -1, 0};
inline constexpr array<int, 8> DY8 = {0, -1, -1, -1, 0, 1, 1, 1};
inline constexpr array<int, 8> DX8 = {1, 1, 0, -1, -1, -1, 0, 1};
inline constexpr char LF = '\n';
#line 2 "template/macro.hpp"
#line 5 "template/macro.hpp"
/**
* @see https://trap.jp/post/1224/
*/
#ifdef LOCAL
inline constexpr bool IS_LOCAL = true;
#else
inline constexpr bool IS_LOCAL = false;
#endif
#define IF_LOCAL if constexpr (IS_LOCAL)
#define all(a) begin(a), end(a)
#define rall(a) rbegin(a), rend(a)
#define overload4(a, b, c, d, e, ...) e
#define rep1(i, a) for (ll i = 0; (i) < (ll)(a); ++(i))
#define rep2(i, a, b) for (ll i = (ll)(a); (i) < (ll)(b); ++(i))
#define rep3(i, a, b, c) for (ll i = (ll)(a); (i) < (ll)(b); (i) += (ll)(c))
#define rep(...) overload4(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define rrep1(i, a) for (ll i = (ll)(a); (i) >= 0; --(i))
#define rrep2(i, a, b) for (ll i = (ll)(a); (i) >= (ll)(b); --(i))
#define rrep3(i, a, b, c) for (ll i = (ll)(a); (i) >= (ll)(b); (i) -= (ll)(c))
#define rrep(...) overload4(__VA_ARGS__, rrep3, rrep2, rrep1)(__VA_ARGS__)
#line 13 "template/template.hpp"
#line 2 "utility/choose_min_max.hpp"
/**
* @title Choose Minimum / Maximum
*/
template <class T>
bool chmin(T& a, const T& b) {
if (a > b) {
a = b;
return true;
}
return false;
}
template <class T>
bool chmax(T& a, const T& b) {
if (a < b) {
a = b;
return true;
}
return false;
}
#line 2 "utility/set_io.hpp"
#line 4 "utility/set_io.hpp"
void set_io(int d = 16) {
cin.tie(nullptr);
ios_base::sync_with_stdio(false);
cout << fixed << setprecision(d);
return;
}
#line 4 "math/binomial.hpp"
/**
* @brief Binomial (二項係数)
* @note 参考: https://blog.hamayanhamayan.com/entry/2018/06/06/210256
*/
template <class T>
class Binomial {
private:
int n;
vector<T> fact, ifact;
public:
Binomial() : Binomial(0) {}
Binomial(int _n) : n(_n), fact(_n + 1), ifact(_n + 1) {
assert(0 <= _n);
fact[0] = T(1);
rep (i, 0, n) {
fact[i + 1] = fact[i] * T(i + 1);
}
ifact[n] = T(1) / fact[n];
rrep (i, n, 1) {
ifact[i - 1] = ifact[i] * T(i);
}
}
//! 順列
T p(int a, int b) const {
if (b < 0 || a < b) {
return T(0);
}
assert(0 <= a && a <= n);
assert(0 <= a - b && a - b <= n);
return fact[a] * ifact[a - b];
}
//! 組合せ
T c(int a, int b) const {
if (b < 0 || a < b) {
return T(0);
}
assert(0 <= b && b <= n);
return p(a, b) * ifact[b];
}
//! 重複組合せ
T h(int a, int b) const {
if (a == 0 && b == 0) {
return T(1);
}
if (a <= 0 || b < 0) {
return T(0);
}
return c(a + b - 1, b);
}
};