Skip to content

Commit 45807c8

Browse files
committed
v1.0.4:增加了多项式、圆方树和修改其他内容
1 parent cc3502d commit 45807c8

6 files changed

Lines changed: 627 additions & 33 deletions

File tree

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
**当前最新普通版发布版本为 `v1.0.3`****最新打印版发布版本为 `v1.0.0` (总词数约7.7w(含代码))**
1+
**当前最新普通版发布版本为 `v1.0.4`****最新打印版发布版本为 `v1.0.0` (总词数约7.7w(含代码))**
22

33
成品为 `template.pdf` (移步 [releases](https://github.com/lr580/algorithm_template/releases) 查看/下载)
44

@@ -46,13 +46,24 @@
4646

4747
## 更新日志
4848

49+
- 22/06/10 - 22/08/27 (`v1.0.4`)
50+
51+
- 微改了 STL 的 nth\_element 和 inplace\_merge
52+
53+
- 微改了复杂度一节的排版错误
54+
- 删除了 STL 的 string 重复内容
55+
- 添加了多项式一节,增加 NTT 和分治 FFT 内容
56+
- 修正了线段树区间最值例题表述错误
57+
- 更换了欧拉筛一道例题
58+
- 添加了 tarjan 算法求点双连通分量和圆方树内容
59+
4960
- 22/05/17 - 22/05/25 (`v1.0.3`)
5061

5162
- 增加了stringstream
5263
- 增加了普通莫队、带修莫队、树上莫队和回滚莫队算法
5364
- 增加了set部分内容
5465
- 增加了2-SAT算法
55-
66+
5667
- 22/04/19 - 22/04/22 (`v1.0.2`)
5768

5869
- 增加了KMP算法周期与border

code/euler_sample.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//https://oj.socoding.cn/p/1745
2+
#include <bits/stdc++.h>
3+
using namespace std;
4+
typedef long long ll;
5+
#define sc(x) scanf("%lld", &x)
6+
#define mn 1000002
7+
ll n, k, p[mn], pri[mn], e[mn], pe[mn], g[mn], cnt, ans = 1, mod = 1e9 + 7;
8+
void euler(ll n)
9+
{ // e[i]是i质因数分解得到的最大的幂a_i,pe[i]是对应最大的(p^e[i])
10+
for (ll i = 2; i <= n; ++i)
11+
{
12+
if (!p[i])
13+
{
14+
p[i] = i, pri[++cnt] = i, pe[i] = i, e[i] = 1;
15+
}
16+
for (ll j = 1; i * pri[j] <= n; ++j)
17+
{
18+
p[i * pri[j]] = pri[j];
19+
if (pri[j] == p[i])
20+
{
21+
e[i * pri[j]] = e[i] + 1;
22+
pe[i * pri[j]] = pe[i] * pri[j];
23+
break;
24+
}
25+
e[i * pri[j]] = 1;
26+
pe[i * pri[j]] = pri[j];
27+
}
28+
}
29+
}
30+
ll qpow(ll a, ll b)
31+
{
32+
ll res = 1;
33+
for (; b > 0; b >>= 1)
34+
{
35+
if (b & 1)
36+
{
37+
res = res * a % mod;
38+
}
39+
a = a * a % mod;
40+
}
41+
return res;
42+
}
43+
signed main()
44+
{
45+
sc(n), sc(k);
46+
g[1] = 1;
47+
euler(n);
48+
for (ll i = 2; i <= n; ++i)
49+
{
50+
if (pe[i] == i)
51+
{
52+
g[i] = (qpow(p[i], e[i] * k + 1) - 1 + mod) % mod * qpow(p[i] - 1, mod - 2) % mod;
53+
g[i] = g[i] * (qpow(p[i], e[i] * k) - qpow(p[i], e[i] * k - 1) + mod) % mod;
54+
}
55+
else
56+
{
57+
g[i] = g[i / pe[i]] * g[pe[i]] % mod;
58+
}
59+
ans = (ans + g[i]) % mod;
60+
}
61+
printf("%lld", ans);
62+
return 0;
63+
}

code/p3803_ntt.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include <bits/stdc++.h>
2+
using namespace std;
3+
#define sc(x) scanf("%lld", &x)
4+
typedef long long ll;
5+
const ll mn = 3e6 + 10, p = 998244353, g = 3, gi = 332748118;
6+
ll n, m, lim = 1, l, r[mn], a[mn], b[mn]; // 2^l=lim
7+
ll qpow(ll a, ll b)
8+
{
9+
ll r = 1;
10+
for (; b; b >>= 1)
11+
{
12+
if (b & 1)
13+
{
14+
r = r * a % p;
15+
}
16+
a = a * a % p;
17+
}
18+
return r;
19+
}
20+
void ntt(ll *a, ll type)
21+
{
22+
for (ll i = 0; i < lim; ++i)
23+
{
24+
if (i < r[i])
25+
{
26+
swap(a[i], a[r[i]]);
27+
}
28+
}
29+
for (ll mid = 1; mid < lim; mid <<= 1)
30+
{
31+
ll wn = qpow(type == 1 ? g : gi, (p - 1) / (mid << 1));
32+
for (ll j = 0; j < lim; j += (mid << 1))
33+
{
34+
ll w = 1;
35+
for (ll k = 0; k < mid; ++k, w = w * wn % p)
36+
{
37+
ll x = a[j + k], y = w * a[j + k + mid] % p;
38+
a[j + k] = (x + y) % p;
39+
a[j + k + mid] = (x - y + p) % p;
40+
}
41+
}
42+
}
43+
}
44+
signed main()
45+
{
46+
sc(n), sc(m);
47+
for (ll i = 0; i <= n; ++i)
48+
{
49+
sc(a[i]);
50+
}
51+
for (ll i = 0; i <= m; ++i)
52+
{
53+
sc(b[i]);
54+
}
55+
while (lim <= n + m)
56+
{
57+
++l, lim <<= 1;
58+
}
59+
for (ll i = 0; i < lim; ++i)
60+
{
61+
r[i] = (r[i >> 1] >> 1 | ((i & 1) << (l - 1)));
62+
}
63+
ntt(a, 1), ntt(b, 1);
64+
for (ll i = 0; i < lim; ++i)
65+
{
66+
a[i] = a[i] * b[i] % p;
67+
}
68+
ntt(a, -1);
69+
ll inv = qpow(lim, p - 2);
70+
for (ll i = 0; i <= n + m; ++i)
71+
{
72+
printf("%lld ", a[i] * inv % p);
73+
}
74+
return 0;
75+
}

code/partition_fft.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//https://oj.socoding.cn/p/1778
2+
#include <bits/stdc++.h>
3+
using namespace std;
4+
using ll = long long;
5+
using pii = pair<int, int>;
6+
using pll = pair<ll, ll>;
7+
const ll mod = 998244353;
8+
9+
ll qui(ll a, ll x)
10+
{
11+
ll ret = 1;
12+
while (x)
13+
{
14+
if (x & 1)
15+
ret = ret * a % mod;
16+
a = a * a % mod;
17+
x >>= 1;
18+
}
19+
return ret;
20+
}
21+
22+
using Poly = vector<ll>;
23+
const int BIT = 20;
24+
int p[1 << BIT];
25+
const ll maxn = 1e5 + 10;
26+
ll fac[maxn], inv[maxn];
27+
28+
Poly operator*(const Poly &a, const Poly &b)
29+
{
30+
int n = a.size() - 1, m = b.size() - 1;
31+
int L, l = 0;
32+
for (L = 1; L <= n + m; l++, L = L << 1)
33+
;
34+
35+
vector<int> p(L);
36+
37+
for (int i = 1; i < L; i++)
38+
p[i] = ((p[i >> 1] >> 1) | ((i & 1) << (l - 1)));
39+
auto u = a, v = b;
40+
u.resize(L, 0), v.resize(L, 0);
41+
auto ntt = [&L, &l, &p](Poly &g, int type)
42+
{
43+
for (int i = 0; i < L; i++)
44+
if (i < p[i])
45+
swap(g[i], g[p[i]]);
46+
for (int i = 1; i < L; (i <<= 1))
47+
{
48+
ll wn = qui(3, (mod - 1) / (i << 1));
49+
for (int j = 0; j < L; j += (i << 1))
50+
{
51+
ll w = 1;
52+
for (int k = j; k < j + i; w = w * wn % mod, k++)
53+
{
54+
assert(k + i < L);
55+
assert(k < L);
56+
ll t = g[k + i] * w % mod;
57+
g[k + i] = (g[k] - t + mod) % mod;
58+
g[k] = (g[k] + t) % mod;
59+
}
60+
}
61+
}
62+
if (type == 1)
63+
return;
64+
reverse(g.begin() + 1, g.begin() + L);
65+
ll ni = qui(L, mod - 2);
66+
for (int i = 0; i < L; i++)
67+
g[i] = g[i] * ni % mod;
68+
};
69+
ntt(u, 1), ntt(v, 1);
70+
71+
Poly g(L, 0);
72+
for (int i = 0; i < L; i++)
73+
g[i] = u[i] * v[i] % mod;
74+
ntt(g, -1);
75+
76+
return g;
77+
}
78+
79+
signed main()
80+
{
81+
cin.tie(0)->sync_with_stdio(false);
82+
int n, k;
83+
cin >> n >> k;
84+
85+
vector<int> b(n + 1);
86+
for (int i = 1; i <= n; i++)
87+
cin >> b[i];
88+
89+
function<Poly(int, int)> calc = [&](int l, int r)
90+
{
91+
if (l >= r)
92+
{
93+
assert(l == r);
94+
return Poly{1, b[l]};
95+
}
96+
int mid = (l + r) / 2;
97+
return calc(l, mid) * calc(mid + 1, r);
98+
};
99+
100+
Poly ep = calc(0, n);
101+
cout << ep[k];
102+
return 0;
103+
}

code/tarjan_bi_conn.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
ll dfn[mn], low[mn], st, stk[mn], stop, cn;
2+
vector<ll> c[mn]; //点双
3+
void tarjan(ll u)
4+
{
5+
dfn[u] = low[u] = ++st;
6+
stk[++stop] = u;
7+
for (ll i = hd[u]; i; i = e[i].nx)
8+
{
9+
ll v = e[i].to;
10+
if (!dfn[v])
11+
{
12+
tarjan(v);
13+
low[u] = min(low[u], low[v]);
14+
if (low[v] >= dfn[u])
15+
{ //找出新的点双上的所有点
16+
c[++cn].push_back(u);
17+
for (ll w = 0; w != v;)
18+
{
19+
w = stk[stop--];
20+
c[cn].push_back(w);
21+
}
22+
}
23+
}
24+
else
25+
{
26+
low[u] = min(low[u], dfn[v]);
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)