This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "math/number-theory/LCMConvolution.hpp"todo
todo
#include "MultipleDivisorZetaMobiusTransform.hpp"
template <class T>
vector<T> lcm_convolution(vector<T> a, vector<T> b) {
vector<T> za = divisor_zeta(a);
vector<T> zb = divisor_zeta(b);
vector<T> d(a.size());
for (int i = 0; i < a.size(); i++) d[i] = za[i] * zb[i];
return divisor_mobius(d);
}#line 1 "math/number-theory/MultipleDivisorZetaMobiusTransform.hpp"
template <class T>
vector<T> divisor_zeta(vector<T> a) {
int n = int(a.size()) - 1;
vector<bool> prime(n + 1, true);
for (int p = 2; p <= n; p++) {
if (prime[p]) {
for (long long k = 1; k * p <= n; k++) {
prime[k * p] = false;
a[k * p] += a[k];
}
}
}
return a;
}
template <class T>
vector<T> divisor_mobius(vector<T> a) {
int n = int(a.size()) - 1;
vector<bool> prime(n + 1, true);
for (int p = 2; p <= n; p++) {
if (prime[p]) {
for (long long k = n / p; k > 0; k--) {
prime[k * p] = false;
a[k * p] -= a[k];
}
}
}
return a;
}
template <class T>
vector<T> multiple_zeta(vector<T> a) {
int n = int(a.size()) - 1;
vector<bool> prime(n + 1, true);
for (int p = 2; p <= n; p++) {
if (prime[p]) {
for (long long k = n / p; k > 0; k--) {
prime[k * p] = false;
a[k] += a[k * p];
}
}
}
return a;
}
template <class T>
vector<T> multiple_mobius(vector<T> a) {
int n = int(a.size()) - 1;
vector<bool> prime(n + 1, true);
for (int p = 2; p <= n; p++) {
if (prime[p]) {
for (long long k = 1; k * p <= n; k++) {
prime[k * p] = false;
a[k] -= a[k * p];
}
}
}
return a;
}
#line 2 "math/number-theory/LCMConvolution.hpp"
template <class T>
vector<T> lcm_convolution(vector<T> a, vector<T> b) {
vector<T> za = divisor_zeta(a);
vector<T> zb = divisor_zeta(b);
vector<T> d(a.size());
for (int i = 0; i < a.size(); i++) d[i] = za[i] * zb[i];
return divisor_mobius(d);
}