Skip to content

Commit 0459a5a

Browse files
committed
Add and convolution and test
1 parent 0e86671 commit 0459a5a

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

cp-algo/math/and_convolution.hpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#ifndef CP_ALGO_MATH_AND_CONVOLUTION_HPP
2+
#define CP_ALGO_MATH_AND_CONVOLUTION_HPP
3+
#include "../number_theory/modint.hpp"
4+
#include "../util/bit.hpp"
5+
#include "../util/checkpoint.hpp"
6+
7+
namespace cp_algo::math {
8+
enum transform_dir { forward, inverse };
9+
// Recursive Zeta / Möbius (AND) transform for size N (power of two)
10+
template<auto N, transform_dir direction>
11+
void and_transform(auto &&a) {
12+
if constexpr (N == 1) {
13+
return;
14+
} else {
15+
constexpr auto half = N / 2;
16+
and_transform<half, direction>(&a[0]);
17+
and_transform<half, direction>(&a[half]);
18+
for (uint32_t i = 0; i < half; i++) {
19+
if constexpr (direction == forward) {
20+
a[i] += a[i + half];
21+
} else {
22+
a[i] -= a[i + half];
23+
}
24+
}
25+
}
26+
}
27+
// Wrapper that deduces N at compile time via with_bit_floor
28+
template<transform_dir direction>
29+
inline void and_transform(auto &&a, auto n) {
30+
with_bit_floor(n, [&]<auto NN>() {
31+
assert(NN == n);
32+
and_transform<NN, direction>(a);
33+
});
34+
}
35+
template<transform_dir direction = forward>
36+
inline void and_transform(auto &&a) {
37+
and_transform<direction>(a, std::size(a));
38+
}
39+
// In-place AND convolution on sequences of equal length (power of two)
40+
void and_convolution_inplace(auto &a, auto &b) {
41+
auto N = static_cast<uint32_t>(std::size(a));
42+
and_transform(a);
43+
and_transform(b);
44+
checkpoint("transform");
45+
for (uint32_t i = 0; i < N; i++) {
46+
a[i] *= b[i];
47+
}
48+
checkpoint("dot");
49+
and_transform<inverse>(a);
50+
checkpoint("itransform");
51+
}
52+
53+
// Returns AND convolution of a and b; pads to next power of two
54+
auto and_convolution(auto a, auto b) {
55+
auto n = std::bit_ceil(std::max(std::size(a), std::size(b)));
56+
a.resize(n);
57+
b.resize(n);
58+
and_convolution_inplace(a, b);
59+
return a;
60+
}
61+
}
62+
#endif // CP_ALGO_MATH_AND_CONVOLUTION_HPP
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// @brief Bitwise And Convolution
2+
#define PROBLEM "https://judge.yosupo.jp/problem/bitwise_and_convolution"
3+
#pragma GCC optimize("O3,unroll-loops")
4+
#include <bits/allocator.h>
5+
#pragma GCC target("avx2")
6+
#include <iostream>
7+
#include "blazingio/blazingio.min.hpp"
8+
#define CP_ALGO_CHECKPOINT
9+
#include "cp-algo/number_theory/modint.hpp"
10+
#include "cp-algo/util/big_alloc.hpp"
11+
#include "cp-algo/util/checkpoint.hpp"
12+
#include "cp-algo/math/and_convolution.hpp"
13+
#include <bits/stdc++.h>
14+
15+
using namespace std;
16+
17+
const int mod = 998244353;
18+
using base = cp_algo::math::modint<mod>;
19+
20+
void solve() {
21+
uint32_t n;
22+
cin >> n;
23+
uint32_t N = 1u << n;
24+
cp_algo::big_vector<base> a(N), b(N);
25+
for (auto &it : a) {cin >> it;}
26+
for (auto &it : b) {cin >> it;}
27+
cp_algo::checkpoint("read");
28+
cp_algo::math::and_convolution_inplace(a, b);
29+
for (auto it : a) {cout << it << ' ';}
30+
cp_algo::checkpoint("write");
31+
cp_algo::checkpoint<1>();
32+
}
33+
34+
signed main() {
35+
ios::sync_with_stdio(0);
36+
cin.tie(0);
37+
int t = 1;
38+
while (t--) {
39+
solve();
40+
}
41+
}

0 commit comments

Comments
 (0)