Skip to content

Commit

Permalink
feat: upload
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiphereth-A committed Feb 11, 2025
1 parent 8fe1d18 commit ab061ed
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 13 deletions.
3 changes: 3 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,9 @@ notebook:
- gen_pows: 幂次模序列
code_ext: hpp
test_ext: cpp
- gen_ipowi: 二次超幂序列
code_ext: hpp
test_ext: cpp
- gen_bernoulli: Bernoulli 数序列
code_ext: hpp
test_ext: cpp
Expand Down
2 changes: 1 addition & 1 deletion src/code/comb/gen_invseq.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ CEXP vecuu gen_invseq(spnuu v, u64 mod) NE {
if (n == 0) return {};
if (n == 1) return {inverse(v[0], mod)};
vecuu ans(n);
ans[0] = v[1];
ans[0] = v[0];
flt_ (u32, i, 1, n) ans[i] = mul_mod_u(ans[i - 1], v[i], mod);
u64 _ = inverse(ans.back(), mod);
for (u32 i = n - 1; i; --i) ans[i] = mul_mod_u(_, ans[i - 1], mod), _ = mul_mod_u(_, v[i], mod);
Expand Down
66 changes: 66 additions & 0 deletions src/code/comb/gen_ipowi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#ifndef TIFALIBS_COMB_GEN_IPOWI
#define TIFALIBS_COMB_GEN_IPOWI

#include "../math/isqrt.hpp"
#include "../math/qpow_mod.hpp"
#include "../nt/lsieve.hpp"

namespace tifa_libs::math {
namespace gen_ipowi_impl_ {
struct ls_ipowi {
static inline u64 mod;
vecuu ipowi;

protected:
const u32 B;
vvecuu fp, fpb;
u32 pre_j, gap;
u64 now_r;
arr<u64, 355> p{1}; // maximal prime gaps: g_n=354 => p_n=4,302,407,359

CEXPE ls_ipowi(u32 n) NE : ipowi(n), B{isqrt(n)}, fp(B + 1, vecuu(B + 1)), fpb(B + 1, vecuu(B + 1)), pre_j{0}, gap{0}, now_r{1} {
if (n) ipowi[0] = 1;
if (n > 1) ipowi[1] = 1;
}
void prime(u32 p) NE {
if (ipowi[p] = qpow_mod(p, p, mod); p <= B) {
fp[p][0] = 1;
flt_ (u32, j, 1, B + 1)
fp[p][j] = mul_mod_u(fp[p][j - 1], ipowi[p], mod);
fpb[p][0] = 1;
flt_ (u32, j, 1, B + 1)
fpb[p][j] = mul_mod_u(fpb[p][j - 1], fp[p].back(), mod);
}
}
void coprime(u32 i, u32 j) NE {
if (j <= pre_j) now_r = 1, pre_j = gap = 0;
if (u32 new_gap = j - pre_j; new_gap > gap) {
flt_ (u32, x, gap + 1, new_gap + 1) p[x] = mul_mod_u(p[x - 1], ipowi[i], mod);
gap = new_gap;
}
now_r = mul_mod_u(now_r, p[j - pre_j], mod);
ipowi[i * j] = mul_mod_u(mul_mod_u(fp[j][i % B], fpb[j][i / B], mod), now_r, mod);
pre_j = j;
}
void not_coprime(u32 i, u32 j) NE { coprime(i, j); }
};
} // namespace gen_ipowi_impl_

// i^i from i=0..n-1
CEXP vecuu gen_ipowi(u32 n, u64 mod) NE {
if (n < 2) return vecuu(n, 1);
gen_ipowi_impl_::ls_ipowi::mod = mod;
return lsieve<gen_ipowi_impl_::ls_ipowi>(n).ipowi;
}
// i^i from i=0..n-1
template <class mint>
CEXP vec<mint> gen_ipowi(u32 n) NE {
vec<mint> ans(n);
auto _ = gen_ipowi(n, mint::mod());
flt_ (u32, i, 0, n) ans[i] = _[i];
return ans;
}

} // namespace tifa_libs::math

#endif
25 changes: 19 additions & 6 deletions src/code/comb/gen_pows.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,31 @@
#define TIFALIBS_COMB_GEN_POWS

#include "../math/qpow_mod.hpp"
#include "../nt/lsieve.hpp"

namespace tifa_libs::math {
namespace gen_pows_impl_ {
struct ls_pows {
static inline u64 b, mod;
vecuu pows;

protected:
CEXPE ls_pows(u32 n) NE : pows(n) {
if (n > 1) pows[1] = 1;
}
void prime(u32 p) NE { pows[p] = qpow_mod(p, b, mod); }
void coprime(u32 i, u32 j) NE { pows[i * j] = mul_mod_u(pows[i], pows[j], mod); }
void not_coprime(u32 i, u32 j) NE { coprime(i, j); }
};
} // namespace gen_pows_impl_

// i^{b} from i=0..n-1
CEXP vecuu gen_pows(u32 n, u64 b, u64 mod) NE {
if (!b) return vecuu(n, mod > 1);
if (!n) return {};
vecuu ans(n);
if (!b) ans[0] = 1;
if (n == 1) return ans;
ans[1] = 1;
flt_ (u32, i, 2, n) ans[i] = qpow_mod(i, b, mod);
return ans;
gen_pows_impl_::ls_pows::b = b;
gen_pows_impl_::ls_pows::mod = mod;
return lsieve<gen_pows_impl_::ls_pows>(n).pows;
}
// i^{b} from i=0..n-1
template <class mint>
Expand Down
11 changes: 5 additions & 6 deletions src/code/comb/gen_stirling1_col.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
#ifndef TIFALIBS_COMB_GEN_STIRLING1_COL
#define TIFALIBS_COMB_GEN_STIRLING1_COL

#include "../math/fact_helper.hpp"
#include "../poly/pow_fps.hpp"
#include "gen_fact.hpp"
#include "gen_inv.hpp"
#include "gen_invseq.hpp"

namespace tifa_libs::math {

// stirling1[i] = {i \\brack k}, i=0,1,...,n
template <class poly, class T, bool with_sgn = true>
CEXP poly gen_stirling1_col(u32 n, u32 k, vec<T> CR fact, vec<T> CR inv, vec<T> CR invfact) NE {
CEXP poly gen_stirling1_col(u32 n, u32 k, vec<T> CR fact, vec<T> CR inv, vec<T> CR ifact) NE {
if (n < k) return poly(n + 1);
poly f(n + 1);
flt_ (u32, i, 1, n + 1) f[i] = inv[i];
f = pow_fps(f, k) * invfact[k];
f = pow_fps(f, k) * ifact[k];
flt_ (u32, i, k, n + 1) f[i] *= fact[i];
if CEXP (with_sgn)
for (u32 i = k ^ 1; i <= n; i += 2) f[i] = -f[i];
Expand All @@ -24,8 +23,8 @@ CEXP poly gen_stirling1_col(u32 n, u32 k, vec<T> CR fact, vec<T> CR inv, vec<T>
template <class poly, bool with_sgn = true>
CEXP poly gen_stirling1_col(u32 n, u32 k) NE {
using mint = TPN poly::val_t;
auto fact = gen_fact(n + 1, mint::mod());
return gen_stirling1_col<poly, u64, with_sgn>(n, k, fact, gen_inv(n + 1, mint::mod()), gen_invseq(fact, mint::mod()));
fact_helper<mint>::ensure(n + 1);
return gen_stirling1_col<poly, mint, with_sgn>(n, k, fact_helper<mint>::fact, gen_inv<mint>(n + 1), fact_helper<mint>::ifact);
}

} // namespace tifa_libs::math
Expand Down
4 changes: 4 additions & 0 deletions src/doc_md/comb/gen_ipowi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: gen_ipowi
documentation_of: //src/code/comb/gen_ipowi.hpp
---
1 change: 1 addition & 0 deletions src/doc_tex/comb/gen_ipowi.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
\paragraph{参考链接} \qrcode{https://www.cnblogs.com/wlzhouzhuan/p/16104029.html}
95 changes: 95 additions & 0 deletions src/test_cpverifier/unit-test/comb/gen.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#define UNITTEST
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"

#include "../../../code/comb/gen_fact.hpp"
#include "../../../code/comb/gen_ifact.hpp"
#include "../../../code/comb/gen_inv.hpp"
#include "../../../code/comb/gen_invseq.hpp"
#include "../../../code/comb/gen_ipowi.hpp"
#include "../../../code/comb/gen_pows.hpp"
#include "../../../code/math/mint.hpp"
#include "../../../code/math/mint_d31.hpp"
#include "../../../code/math/mint_d63.hpp"
#include "../../../code/math/mint_s30.hpp"
#include "../../../code/math/mint_s63.hpp"
#include "../../../code/math/qpow.hpp"
#include "../base.hpp"

tifa_libs::rand::Gen<u64> g(1);

template <class mint>
void test_all(u32 n) {
[](u32 n) { // fact & ifact
auto fact = tifa_libs::math::gen_fact<mint>(n);
auto ifact = tifa_libs::math::gen_ifact<mint>(n);
mint bf = 1;
flt_ (u32, i, 0, n) {
if (i) bf *= i;
check(fact[i], bf, check_param(i));
check(ifact[i], bf.inv(), check_param(i));
}
}(n);
[](u32 n) { // inv
auto inv = tifa_libs::math::gen_inv<mint>(n);
flt_ (u32, i, 1, n) {
auto bf = mint{i}.inv();
check(inv[i], bf, check_param(i));
}
}(n);
[](u32 n) { // invseq
vec<mint> seq;
std::generate_n(std::back_inserter(seq), n, [&] { return mint(g()); });
auto invseq = tifa_libs::math::gen_invseq(seq);
flt_ (u32, i, 0, n) {
auto bf = seq[i].inv();
check(invseq[i], bf, check_param(i), check_param(seq[i]));
}
}(n);
[](u32 n) { // ipowi
auto ipowi = tifa_libs::math::gen_ipowi<mint>(n);
flt_ (u32, i, 0, n) {
auto bf = tifa_libs::math::qpow<mint>(i, i);
check(ipowi[i], bf, check_param(i));
}
}(n);
auto test_pows = [](u32 n, u32 b) { // pows
auto pows = tifa_libs::math::gen_pows<mint>(n, b);
flt_ (u32, i, 0, n) {
auto bf = tifa_libs::math::qpow<mint>(i, b);
check(pows[i], bf, check_param(i), check_param(b));
}
};
test_pows(n, 0);
test_pows(n, 1);
test_pows(n, 114514);
test_pows(n, n);
}

using mints30 = tifa_libs::math::mint<tifa_libs::math::mint_s30, 998244353>;
using mints63 = tifa_libs::math::mint<tifa_libs::math::mint_s63, 998244353>;
using mintd31 = tifa_libs::math::mint<tifa_libs::math::mint_d31, __LINE__>;
using mintd63 = tifa_libs::math::mint<tifa_libs::math::mint_d63, __LINE__>;

int main() {
auto tcase = tifa_libs::unittest::pre_test();
mintd31::set_mod(1000000000 + 7);
mintd63::set_mod(1000000000 + 7);

switch (tcase) {
case tifa_libs::unittest::ts_example_00: test_all<mints30>(1000); break;
case tifa_libs::unittest::ts_example_01: test_all<mints63>(1000); break;
case tifa_libs::unittest::ts_random_00: test_all<mintd31>(1000); break;
case tifa_libs::unittest::ts_random_01: test_all<mintd63>(1000); break;
case tifa_libs::unittest::ts_random_02: test_all<mints30>(1'000'000); break;
case tifa_libs::unittest::ts_random_03: test_all<mints63>(1'000'000); break;
case tifa_libs::unittest::ts_random_04: test_all<mintd31>(1'000'000); break;
case tifa_libs::unittest::ts_random_05: test_all<mintd63>(1'000'000); break;
case tifa_libs::unittest::ts_random_06: break;
case tifa_libs::unittest::ts_random_07: break;
case tifa_libs::unittest::ts_random_08: break;
case tifa_libs::unittest::ts_random_09: break;
default: break;
}

tifa_libs::unittest::post_test();
}
Empty file.

0 comments on commit ab061ed

Please sign in to comment.