Skip to content

Commit 8c975a7

Browse files
committed
add
1 parent 10bdff5 commit 8c975a7

7 files changed

+238
-0
lines changed

docs/fps/sparse.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
sparse な FPS についての各種 FPS 演算.
2+
与えられた FPS で非ゼロの項が $K$ 項で,$N$ 次まで求めるとき $O(NK)$ 時間.
3+
4+
以下の等式から係数についての sparse な漸化式が得られる.
5+
6+
- inv : $fg=1$
7+
- exp : $g'=f'g$
8+
- log : $fg'=f'$
9+
- pow : $fg'=Mf'g$
10+
- sqrt : $f=g^2$

fps/sparse.hpp

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#pragma once
2+
#include "modint/factorial.hpp"
3+
#include "modint/mod-sqrt.hpp"
4+
#include "fps/formal-power-series.hpp"
5+
6+
namespace FPSSparse {
7+
template <class mint>
8+
FormalPowerSeries<mint> inv(map<int, mint> f, int n) {
9+
assert(f[0] != 0);
10+
if (n == 0) return {};
11+
mint c = f[0].inv();
12+
FormalPowerSeries<mint> g(n);
13+
g[0] = c;
14+
for (int i = 1; i < n; i++) {
15+
for (auto [j, v] : f)
16+
if (j <= i) g[i] -= v * g[i - j];
17+
g[i] *= c;
18+
}
19+
return g;
20+
}
21+
template <class mint>
22+
FormalPowerSeries<mint> exp(map<int, mint> f, int n) {
23+
assert(f[0] == 0);
24+
if (n == 0) return {};
25+
FormalPowerSeries<mint> g(n);
26+
g[0] = 1;
27+
for (int i = 1; i < n; i++) {
28+
for (auto [j, v] : f)
29+
if (j <= i) g[i] += j * v * g[i - j];
30+
g[i] *= Factorial<mint>::inv(i);
31+
}
32+
return g;
33+
}
34+
template <class mint>
35+
FormalPowerSeries<mint> log(map<int, mint> f, int n) {
36+
assert(f[0] == 1);
37+
if (n == 0) return {};
38+
FormalPowerSeries<mint> g(n);
39+
g[0] = 0;
40+
for (auto [j, v] : f)
41+
if (0 < j && j < n) g[j - 1] = v * j;
42+
for (int i = 1; i < n; i++) {
43+
for (auto [j, v] : f)
44+
if (0 < j && j <= i) g[i] -= v * g[i - j];
45+
}
46+
for (int i = n - 1; i > 0; i--) g[i] = g[i - 1] * Factorial<mint>::inv(i);
47+
g[0] = 0;
48+
return g;
49+
}
50+
template <class mint>
51+
FormalPowerSeries<mint> pow(map<int, mint> f, long long m, int n) {
52+
if (n == 0) return {};
53+
FormalPowerSeries<mint> g(n, 0);
54+
if (m == 0) {
55+
g[0] = 1;
56+
return g;
57+
}
58+
if (f[0] == 0) {
59+
if (m >= n) return g;
60+
int s = 1;
61+
while (s < n && f[s] == 0) s++;
62+
if (s * m >= n) return g;
63+
map<int, mint> f1;
64+
for (auto [i, v] : f) f1[i - s] = v;
65+
auto g1 = pow(f1, m, int(n - s * m));
66+
copy(g1.begin(), g1.end(), g.begin() + int(s * m));
67+
return g;
68+
}
69+
g[0] = f[0].pow(m);
70+
mint c = f[0].inv();
71+
for (int i = 1; i < n; i++) {
72+
for (auto [j, v] : f) {
73+
if (0 < j && j <= i) g[i] += j * f[j] * g[i - j] * m;
74+
if (0 < j && j < i) g[i] -= f[j] * (i - j) * g[i - j];
75+
}
76+
g[i] *= c * Factorial<mint>::inv(i);
77+
}
78+
return g;
79+
}
80+
template <class mint>
81+
FormalPowerSeries<mint> sqrt(map<int, mint> f, int n) {
82+
if (n == 0) return {};
83+
if (f.empty()) return FormalPowerSeries<mint>(n, 0);
84+
FormalPowerSeries<mint> g(n, 0);
85+
if (f[0] == 0) {
86+
int s = 1;
87+
while (s < n * 2 && f[s] == 0) s++;
88+
if (s & 1) return {};
89+
s /= 2;
90+
if (s >= n) return g;
91+
map<int, mint> f1;
92+
for (auto [i, v] : f) f1[i - s * 2] = v;
93+
auto g1 = sqrt(f1, int(n - s));
94+
if (g1.empty()) return {};
95+
copy(g1.begin(), g1.end(), g.begin() + s);
96+
return g;
97+
}
98+
long long sq = ModSqrt(f[0].val(), mint::get_mod());
99+
if (sq < 0) return {};
100+
g[0] = sq;
101+
mint c = f[0].inv(), inv2 = mint(2).inv();
102+
for (int i = 1; i < n; i++) {
103+
for (auto [j, v] : f) {
104+
if (0 < j && j <= i) g[i] += j * f[j] * g[i - j] * inv2;
105+
if (0 < j && j < i) g[i] -= f[j] * (i - j) * g[i - j];
106+
}
107+
g[i] *= c * Factorial<mint>::inv(i);
108+
}
109+
return g;
110+
}
111+
}; // namespace FPSSparse
112+
113+
/**
114+
* @brief Sparse な FPS 演算
115+
* @docs docs/fps/sparse.md
116+
*/
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/exp_of_formal_power_series_sparse"
2+
3+
#include "template/template.hpp"
4+
#include "modint/modint.hpp"
5+
using mint = ModInt<998244353>;
6+
#include "fps/fps-ntt-friendly.hpp"
7+
using fps = FormalPowerSeries<mint>;
8+
#include "fps/sparse.hpp"
9+
10+
int main() {
11+
int n, k;
12+
in(n, k);
13+
map<int, mint> f;
14+
rep(i, 0, k) {
15+
int j;
16+
mint a;
17+
in(j, a);
18+
f[j] = a;
19+
}
20+
out(FPSSparse::exp(f, n));
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/inv_of_formal_power_series_sparse"
2+
3+
#include "template/template.hpp"
4+
#include "modint/modint.hpp"
5+
using mint = ModInt<998244353>;
6+
#include "fps/fps-ntt-friendly.hpp"
7+
using fps = FormalPowerSeries<mint>;
8+
#include "fps/sparse.hpp"
9+
10+
int main() {
11+
int n, k;
12+
in(n, k);
13+
map<int, mint> f;
14+
rep(i, 0, k) {
15+
int j;
16+
mint a;
17+
in(j, a);
18+
f[j] = a;
19+
}
20+
out(FPSSparse::inv(f, n));
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/log_of_formal_power_series_sparse"
2+
3+
#include "template/template.hpp"
4+
#include "modint/modint.hpp"
5+
using mint = ModInt<998244353>;
6+
#include "fps/fps-ntt-friendly.hpp"
7+
using fps = FormalPowerSeries<mint>;
8+
#include "fps/sparse.hpp"
9+
10+
int main() {
11+
int n, k;
12+
in(n, k);
13+
map<int, mint> f;
14+
rep(i, 0, k) {
15+
int j;
16+
mint a;
17+
in(j, a);
18+
f[j] = a;
19+
}
20+
out(FPSSparse::log(f, n));
21+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/pow_of_formal_power_series_sparse"
2+
3+
#include "template/template.hpp"
4+
#include "modint/modint.hpp"
5+
using mint = ModInt<998244353>;
6+
#include "fps/fps-ntt-friendly.hpp"
7+
using fps = FormalPowerSeries<mint>;
8+
#include "fps/sparse.hpp"
9+
10+
int main() {
11+
int n, k;
12+
ll m;
13+
in(n, k, m);
14+
map<int, mint> f;
15+
rep(i, 0, k) {
16+
int j;
17+
mint a;
18+
in(j, a);
19+
f[j] = a;
20+
}
21+
out(FPSSparse::pow(f, m, n));
22+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/pow_of_formal_power_series_sparse"
2+
3+
#include "template/template.hpp"
4+
#include "modint/modint.hpp"
5+
using mint = ModInt<998244353>;
6+
#include "fps/fps-ntt-friendly.hpp"
7+
using fps = FormalPowerSeries<mint>;
8+
#include "fps/sparse.hpp"
9+
10+
#include "fps/fps-sqrt.hpp"
11+
12+
int main() {
13+
int n, k;
14+
in(n, k);
15+
map<int, mint> f;
16+
rep(i, 0, k) {
17+
int j;
18+
mint a;
19+
in(j, a);
20+
f[j] = a;
21+
}
22+
auto g = FPSSparse::sqrt(f, n);
23+
if (g.empty())
24+
out(-1);
25+
else
26+
out(g);
27+
}

0 commit comments

Comments
 (0)