C++ Library for Competitive Programming
/*
* @title 数学/畳み込み/高速メビウス変換
*
* verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2446
* verification-helper: ERROR 1e-7
*/
#include <cmath>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>
#include "emthrm/math/convolution/fast_mobius_transform.hpp"
int main() {
int n;
long long m;
std::cin >> n >> m;
std::vector<long long> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
std::vector<double> p(n);
for (int i = 0; i < n; ++i) {
std::cin >> p[i];
p[i] /= 100;
}
std::vector<long long> g(1 << n, 0);
for (int i = 1; i < (1 << n); ++i) {
long long l = 1;
for (int j = 0; j < n; ++j) {
if (i >> j & 1) {
l /= std::gcd(l, a[j]);
if (l > m / a[j]) {
l = m + 1;
break;
}
l *= a[j];
}
}
g[i] = m / l;
}
g = emthrm::fast_mobius_transform<false>(g);
double ans = 0;
for (int bit = 0; bit < (1 << n); ++bit) {
double prob = 1;
for (int i = 0; i < n; ++i) {
prob *= (bit >> i & 1 ? p[i] : 1 - p[i]);
}
ans += prob * std::abs(g[bit]);
}
std::cout << std::fixed << std::setprecision(8) << ans << '\n';
return 0;
}
#line 1 "test/math/convolution/fast_mobius_transform.test.cpp"
/*
* @title 数学/畳み込み/高速メビウス変換
*
* verification-helper: PROBLEM http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2446
* verification-helper: ERROR 1e-7
*/
#include <cmath>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>
#line 1 "include/emthrm/math/convolution/fast_mobius_transform.hpp"
#include <bit>
#line 6 "include/emthrm/math/convolution/fast_mobius_transform.hpp"
namespace emthrm {
template <bool ADDS_SUPERSET, typename T>
std::vector<T> fast_mobius_transform(std::vector<T> a, const T id = 0) {
const int n = std::bit_ceil(a.size());
a.resize(n, id);
for (int i = 1; i < n; i <<= 1) {
for (int s = 0; s < n; ++s) {
if (s & i) continue;
if constexpr (ADDS_SUPERSET) {
a[s] -= a[s | i];
} else {
a[s | i] -= a[s];
}
}
}
return a;
}
} // namespace emthrm
#line 15 "test/math/convolution/fast_mobius_transform.test.cpp"
int main() {
int n;
long long m;
std::cin >> n >> m;
std::vector<long long> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
std::vector<double> p(n);
for (int i = 0; i < n; ++i) {
std::cin >> p[i];
p[i] /= 100;
}
std::vector<long long> g(1 << n, 0);
for (int i = 1; i < (1 << n); ++i) {
long long l = 1;
for (int j = 0; j < n; ++j) {
if (i >> j & 1) {
l /= std::gcd(l, a[j]);
if (l > m / a[j]) {
l = m + 1;
break;
}
l *= a[j];
}
}
g[i] = m / l;
}
g = emthrm::fast_mobius_transform<false>(g);
double ans = 0;
for (int bit = 0; bit < (1 << n); ++bit) {
double prob = 1;
for (int i = 0; i < n; ++i) {
prob *= (bit >> i & 1 ? p[i] : 1 - p[i]);
}
ans += prob * std::abs(g[bit]);
}
std::cout << std::fixed << std::setprecision(8) << ans << '\n';
return 0;
}