#include template using vc = std::vector; struct CustomHash { static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } }; using i64 = int64_t; #define for_(i, l, r, vars...) \ for (std::make_signed_t i = (l), i##end = (r), ##vars; \ i <= i##end; \ ++i) #define rfor_(i, r, l, vars...) \ for (std::make_signed_t i = (r), i##end = (l), ##vars; \ i >= i##end; \ --i) #define all_(a) (a).begin(), (a).end() template constexpr auto chkmin(Tp &a, Tp b) -> bool { return b < a ? a = b, true : false; } template constexpr auto chkmax(Tp &a, Tp b) -> bool { return a < b ? a = b, true : false; } template constexpr auto ispow2(Tp i) -> bool { return i && (i & -i) == i; } #define TPL_SIZE_(Tuple) std::tuple_size_v> namespace tuple_detail_ { template constexpr auto subtuple_impl_(Tuple &&t, std::index_sequence) { return std::make_tuple(std::get(t)...); } template constexpr auto apply2_impl_(BinOp &&f, Tuple &&lhs, Tuple &&rhs, std::index_sequence) { return std::make_tuple( std::forward(f)(std::get(lhs), std::get(rhs))...); } } // namespace tuple_detail_ template constexpr auto subtuple(Tuple &&t) { static_assert(Begin <= TPL_SIZE_(Tuple) && Len <= TPL_SIZE_(Tuple) && Begin + Len <= TPL_SIZE_(Tuple), "Out of range"); return tuple_detail_::subtuple_impl_(t, std::make_index_sequence()); } template constexpr auto tuple_push(Tp &&v, Tuple &&t) { static_assert(TPL_SIZE_(Tuple) > 0, "Pop from empty tuple"); return std::tuple_cat(subtuple<0, Pos>(t), std::make_tuple(v), subtuple(t)); } template constexpr auto tuple_push_front(Tp &&v, Tuple &&t) { return tuple_push<0>(v, t); } template constexpr auto tuple_push_back(Tp &&v, Tuple &&t) { return tuple_push(v, t); } template constexpr auto tuple_pop(Tuple &&t) { static_assert(TPL_SIZE_(Tuple) > 0, "Pop from empty tuple"); return std::tuple_cat(subtuple<0, Pos>(t), subtuple(t)); } template constexpr auto tuple_pop_front(Tuple &&t) { return tuple_pop<0>(t); } template constexpr auto tuple_pop_back(Tuple &&t) { return tuple_pop(t); } template constexpr auto apply2(BinOp &&f, Tuple &&lhs, Tuple &&rhs) { return tuple_detail_::apply2_impl_( f, lhs, rhs, std::make_index_sequence()); } #define OO_PTEQ_(op) \ template \ constexpr auto operator op(std::pair lhs, \ const std::pair &rhs) { \ return {lhs.first op rhs.first, lhs.second op rhs.second}; \ } \ template \ constexpr auto operator op(std::tuple const &lhs, \ std::tuple const &rhs) { \ return apply2([](auto &&l, auto &&r) { return l op r; }, lhs, rhs); \ } \ template \ constexpr std::pair &operator op##=(std::pair &lhs, \ const std::pair &rhs) { \ lhs.first op## = rhs.first; \ lhs.second op## = rhs.second; \ return lhs; \ } \ template \ constexpr auto operator op##=(std::tuple &lhs, \ const std::tuple &rhs) { \ return lhs = lhs op rhs; \ } OO_PTEQ_(+) OO_PTEQ_(-) OO_PTEQ_(*) OO_PTEQ_(/) OO_PTEQ_(%) OO_PTEQ_(&) OO_PTEQ_(|) OO_PTEQ_(^) OO_PTEQ_(<<) OO_PTEQ_(>>) #undef OO_PTEQ_ #undef TPL_SIZE_ template std::istream &operator>>(std::istream &is, std::pair &p) { return is >> p.first >> p.second; } template std::ostream &operator<<(std::ostream &os, const std::pair &p) { return os << p.first << ' ' << p.second; } template std::istream &operator>>(std::istream &is, std::tuple &p) { std::apply([&](Ts &...targs) { ((is >> targs), ...); }, p); return is; } template std::ostream &operator<<(std::ostream &os, const std::tuple &p) { std::apply( [&](Ts const &...targs) { std::size_t n{0}; ((os << targs << (++n != sizeof...(Ts) ? " " : "")), ...); }, p); return os; } template ().begin()), typename Ct::iterator> && std::is_same_v().end()), typename Ct::iterator>> * = nullptr> std::basic_ostream &operator<<(std::basic_ostream &os, const Ct &x) { if (x.begin() == x.end()) return os; for (auto it = x.begin(); it != x.end() - 1; ++it) os << *it << ' '; os << x.back(); return os; } using namespace std; const int prime[] = {2, 3, 5, 7, 11, 13, 17, 19}; const int SP = sizeof(prime) / sizeof(prime[0]); const int S = 1 << SP; struct Node { i64 state, p; Node(): state(0), p(0) {} void reset(i64 x) { state = p = 0; for_(i, 0, SP - 1) if (x % prime[i] == 0) { state |= (1 << i); while (x % prime[i] == 0) x /= prime[i]; } if (x > 1) p = x; } friend bool operator<(Node const &lhs, Node const &rhs) { return lhs.p == rhs.p ? lhs.state < rhs.state : lhs.p < rhs.p; } }; i64 f[S][S], f1[S][S], f2[S][S]; auto solve([[maybe_unused]] int t_ = 0) -> void { i64 n, p; cin >> n >> p; f[0][0] = 1; vc a(n - 1); for_(i, 0, n - 2) a[i].reset(i + 2); sort(all_(a)); i64 cnt = 0; for (auto &&[state, bigp] : a) { if (!bigp || !cnt || bigp != a[cnt - 1].p) { memcpy(f1, f, sizeof(f1)); memcpy(f2, f, sizeof(f2)); } rfor_(i, S - 1, 0) rfor_(j, S - 1, 0) { if (i & j) continue; if (!(j & state)) (f1[state | i][j] += f1[i][j]) %= p; if (!(i & state)) (f2[i][state | j] += f2[i][j]) %= p; } if (!bigp || cnt == n - 2 || bigp != a[cnt + 1].p) for_(i, 0, S - 1) for_(j, 0, S - 1) { if (i & j) continue; f[i][j] = (f1[i][j] + f2[i][j] + p - f[i][j]) % p; } ++cnt; } i64 ans = 0; for_(i, 0, S - 1) for_(j, 0, S - 1) { if (i & j) continue; ans += f[i][j]; } cout << ans % p; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int i_ = 0; solve(i_); return 0; }