use std::collections::HashMap; use proconio::input; const MOD: i64 = 998244353; // ------------------------------ // Combination Calculator // ------------------------------ struct CombinationCalculator { fact: Vec, inv_fact: Vec, modv: i64, } impl CombinationCalculator { fn new(size: usize, modv: i64) -> Self { let mut fact = vec![0; size + 1]; fact[0] = 1; for i in 1..=size { fact[i] = fact[i - 1] * (i as i64) % modv; } let mut inv_fact = vec![0; size + 1]; inv_fact[size] = mod_pow(fact[size], modv - 2, modv); for i in (0..size).rev() { inv_fact[i] = inv_fact[i + 1] * ((i + 1) as i64) % modv; } Self { fact, inv_fact, modv } } fn comb(&self, n: usize, r: usize) -> i64 { if n < r { return 0; } self.fact[n] * self.inv_fact[r] % self.modv * self.inv_fact[n - r] % self.modv } } // ------------------------------ // mod pow // ------------------------------ fn mod_pow(mut base: i64, mut exp: i64, m: i64) -> i64 { let mut res = 1; base %= m; while exp > 0 { if exp & 1 == 1 { res = res * base % m; } base = base * base % m; exp >>= 1; } res } // ------------------------------ // DFSで状態列挙 // ------------------------------ fn dfs( k_primes_array: &Vec<(i64, usize)>, index: usize, p: i64, p_list: &mut Vec, p_to_list_map: &mut HashMap>, ) { if index == k_primes_array.len() { p_to_list_map.insert(p, p_list.clone()); return; } let (p0, value) = k_primes_array[index]; let mut q = 1; for v in 0..=value { p_list.push(v); dfs(k_primes_array, index + 1, p * q, p_list, p_to_list_map); p_list.pop(); q *= p0; } } fn main() { input! { n: usize, mut k: i64, a_vec: [i64; n], } if k == 1 { println!("{}", (mod_pow(2, n as i64, MOD) - 1 + MOD) % MOD); return; } let base_k = k; // ------------------------------ // 素因数分解 // ------------------------------ let mut k_primes: HashMap = HashMap::new(); let mut p = 2; while p * p <= k { if k % p == 0 { let mut cnt = 0; while k % p == 0 { k /= p; cnt += 1; } k_primes.insert(p, cnt); } p += 1; } if k > 1 { k_primes.insert(k, 1); } let mut k_primes_array: Vec<(i64, usize)> = k_primes.into_iter().collect(); k_primes_array.sort_by_key(|x| x.0); // ------------------------------ // 状態列挙 // ------------------------------ let mut p_to_list_map: HashMap> = HashMap::new(); dfs( &k_primes_array, 0, 1, &mut Vec::new(), &mut p_to_list_map, ); // ------------------------------ // 遷移テーブル // ------------------------------ let mut transition: HashMap<(i64, i64), i64> = HashMap::new(); for (&from_p, from_list) in p_to_list_map.iter() { for (&trans_p, trans_list) in p_to_list_map.iter() { let mut q = 1; for j in 0..k_primes_array.len() { let (p, max_v) = k_primes_array[j]; let exp = std::cmp::min(max_v, from_list[j] + trans_list[j]); q *= p.pow(exp as u32); } transition.insert((from_p, trans_p), q); } } // ------------------------------ // Aを圧縮(freq) // ------------------------------ let mut a_array: HashMap = HashMap::new(); for mut a in a_vec { let mut q = 1; for &(p, value) in &k_primes_array { let mut x = 0; while a % p == 0 { a /= p; x += 1; } x = std::cmp::min(value, x); q *= p.pow(x as u32); } *a_array.entry(q).or_insert(0) += 1; } let combi = CombinationCalculator::new(n, MOD); // ------------------------------ // DP // ------------------------------ let mut dp: HashMap = HashMap::new(); dp.insert(1, 1); for (&a, &freq_q) in a_array.iter() { let mut new_dp = dp.clone(); for (&key_p, &value) in dp.iter() { let mut key_p0 = key_p; for q in 1..=freq_q { let new_key = transition[&(key_p0, a)]; let add = value * combi.comb(freq_q, q) % MOD; *new_dp.entry(new_key).or_insert(0) += add; *new_dp.get_mut(&new_key).unwrap() %= MOD; key_p0 = new_key; } } dp = new_dp; } // ------------------------------ // 出力 // ------------------------------ if let Some(&ans) = dp.get(&base_k) { println!("{}", ans); } else { println!("0"); } }