#pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include #include #define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++) using namespace atcoder; using namespace std; typedef long long ll; using mint = modint998244353; vector divisor(ll n) { auto mod_mul = [](ll a, ll b, ll mod) -> ll { return (__int128)a * b % mod; }; auto mod_pow = [&](ll base, ll exp, ll mod) -> ll { ll result = 1; base %= mod; while (exp) { if (exp & 1) result = mod_mul(result, base, mod); base = mod_mul(base, base, mod); exp >>= 1; } return result; }; auto is_prime = [&](ll num) -> bool { if (num < 2) return false; int smallPrimes[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; for (int p : smallPrimes) { if (num == p) return true; if (num % p == 0) return false; } ll d = num - 1; int s = 0; while ((d & 1) == 0) { d /= 2; s++; } ll testPrimes[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}; for (ll a : testPrimes) { if (a % num == 0) continue; ll x = mod_pow(a, d, num); if (x == 1 || x == num - 1) continue; bool composite = true; for (int i = 0; i < s - 1; i++) { x = mod_mul(x, x, num); if (x == num - 1) { composite = false; break; } } if (composite) return false; } return true; }; function pollard_rho; pollard_rho = [&](ll num) -> ll { if (num % 2 == 0) return 2; mt19937_64 rng(random_device{}()); uniform_int_distribution dist(2, num - 2); ll x = dist(rng), y = x, c = dist(rng), d = 1; auto f = [&](ll x, ll c, ll mod) -> ll { return (mod_mul(x, x, mod) + c) % mod; }; while (d == 1) { x = f(x, c, num); y = f(y, c, num); y = f(y, c, num); d = gcd(abs(x - y), num); if (d == num) return pollard_rho(num); } return d; }; function &)> factorize; factorize = [&](ll num, vector &factors) { if (num == 1) return; if (is_prime(num)) { factors.push_back(num); return; } ll factor = pollard_rho(num); factorize(factor, factors); factorize(num / factor, factors); }; vector factors; factorize(n, factors); sort(factors.begin(), factors.end()); vector> factorCounts; for (ll f : factors) { if (factorCounts.empty() || factorCounts.back().first != f) factorCounts.push_back({f, 1}); else factorCounts.back().second++; } vector divisors; function dfs = [&](int idx, ll current) { if (idx == factorCounts.size()) { divisors.push_back(current); return; } ll prime = factorCounts[idx].first; int exp = factorCounts[idx].second; for (int i = 0; i <= exp; i++) { dfs(idx + 1, current); current *= prime; } }; dfs(0, 1); sort(divisors.begin(), divisors.end()); return divisors; } struct Comb { vector fact, ifact; int MAX_COM; Comb() {} Comb(int n, int mod) { MAX_COM = n; init(mod, MAX_COM); } void init(long long MOD, long long MAX_COM) { int n = MAX_COM; assert(n < MOD); fact = vector(n + 1); ifact = vector(n + 1); fact[0] = 1; for (int i = 1; i <= n; ++i) fact[i] = fact[i - 1] * i; ifact[n] = fact[n].inv(); for (int i = n; i >= 1; --i) ifact[i - 1] = ifact[i] * i; } mint operator()(long long n, long long k) { if (k < 0 || k > n) return 0; return fact[n] * ifact[k] * ifact[n - k]; } }; Comb comb(5000010, 998244353); template ostream &operator<<(ostream &os, const vector &v) { int n = v.size(); rep(i, 0, n) { os << v[i] << " \n"[i == n - 1]; } return os; } void solve() { ll n, k; cin >> n >> k; vector a(n); unordered_map ma, revd; rep(i, 0, n) { cin >> a[i]; a[i] = gcd(a[i], k); ma[a[i]]++; } auto div = divisor(k); rep(i, 0, div.size()) { revd[div[i]] = i; } int d = div.size(); vector dp(d); dp[0] = 1; rep(i, 0, d) { int cnt = ma[div[i]]; vector ndp(d); rep(j, 0, d) { if (dp[j] == 0) continue; ll cur = div[j]; mint all = pow_mod(2, cnt, 998244353); for (int c = 0; c <= cnt; c++) { ndp[revd[cur]] += dp[j] * comb(cnt, c); all -= comb(cnt, c); ll ne = gcd(cur * div[i], k); if (ne == cur) { ndp[revd[cur]] += dp[j] * all; break; } else { cur = ne; } } } dp = ndp; } cout << dp[d - 1].val() << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout << fixed << setprecision(15); solve(); }