結果
問題 |
No.2313 Product of Subsequence (hard)
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:14:25 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 7,031 bytes |
コンパイル時間 | 1,655 ms |
コンパイル使用メモリ | 103,800 KB |
実行使用メモリ | 16,072 KB |
最終ジャッジ日時 | 2025-05-14 13:15:41 |
合計ジャッジ時間 | 11,383 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 10 TLE * 1 -- * 16 |
ソースコード
#include <iostream> #include <vector> #include <numeric> #include <map> #include <vector> #include <cmath> // Not strictly needed but can be useful #include <algorithm> // For std::min // Define the modulus const long long MOD = 998244353; // Modular exponentiation: computes (base^exp) % MOD long long power(long long base, long long exp) { long long res = 1; base %= MOD; while (exp > 0) { if (exp % 2 == 1) res = (res * base) % MOD; base = (base * base) % MOD; exp /= 2; } return res; } // Structure to hold a prime factor and its required exponent in K struct PrimeFactor { long long p; // prime factor int e; // required exponent }; // Function to prime factorize K // Returns a vector of PrimeFactor structs std::vector<PrimeFactor> prime_factorize(long long k) { std::vector<PrimeFactor> factors; long long temp_k = k; // Use a temporary variable to preserve k if needed // Iterate through potential prime factors up to sqrt(temp_k) for (long long i = 2; i * i <= temp_k; ++i) { if (k % i == 0) { // If i is a factor of k int count = 0; // Divide k by i repeatedly and count the occurrences while (k % i == 0) { k /= i; count++; } // Store the prime factor and its exponent factors.push_back({i, count}); } } // If k is still greater than 1 after the loop, the remaining k is a prime factor itself if (k > 1) { factors.push_back({k, 1}); } return factors; } int main() { // Use fast I/O std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int N; // Number of elements in sequence A long long K; // The divisor K std::cin >> N >> K; std::vector<long long> A(N); // Sequence A for (int i = 0; i < N; ++i) { std::cin >> A[i]; } // Handle the trivial case K=1 // Any non-empty subsequence product is a multiple of 1. // The total number of non-empty subsequences is 2^N - 1. if (K == 1) { long long total_subsequences = power(2, N); long long ans = (total_subsequences - 1 + MOD) % MOD; // Calculate (2^N - 1) mod MOD std::cout << ans << std::endl; return 0; } // Factorize K into its prime factors and their exponents std::vector<PrimeFactor> k_factors = prime_factorize(K); int m = k_factors.size(); // Number of distinct prime factors of K // Calculate the size of each dimension in the DP state space // The k-th dimension corresponds to the prime factor p_k, and its size is e_k + 1 std::vector<int> E_plus_1(m); for (int i = 0; i < m; ++i) { E_plus_1[i] = k_factors[i].e + 1; } // Calculate the total state space size E = product(e_k + 1) // And precompute bases for mapping multi-dimensional state to a single index long long E = 1; // Total number of states std::vector<long long> Bases(m + 1); // Bases B_k for mixed radix representation Bases[0] = 1; for (int i = 0; i < m; ++i) { // Check for potential overflow before multiplication, though unlikely given constraints if (__builtin_mul_overflow(E, E_plus_1[i], &E)) { // This case should not happen for K <= 10^9, as max E is around 512. // Handle error or indicate issue if needed. } // Calculate Bases[i+1] = B_{i+1} = B_i * (e_i + 1) Bases[i+1] = Bases[i] * E_plus_1[i]; } // The final value E represents the total size of the DP state space. // DP state table initialization // dp[idx] stores the number of subsequences processed so far that map to state index idx. std::vector<long long> dp(E, 0); dp[0] = 1; // Base case: The empty subsequence corresponds to state index 0 (all exponents 0), count is 1. // Process each element A[i] of the sequence for (int i = 0; i < N; ++i) { // Compute the capped exponent vector V' for the current element A[i] // V'[k] = min(exponent of p_k in A[i], required exponent e_k) std::vector<int> V_prime(m); long long current_A = A[i]; // Use a copy of A[i] to modify during factorization for (int k = 0; k < m; ++k) { int count = 0; // Efficiently compute the exponent of p_k in A[i], capped at e_k while (count < k_factors[k].e && current_A > 0 && current_A % k_factors[k].p == 0) { current_A /= k_factors[k].p; count++; } V_prime[k] = count; // Store the computed capped exponent } // Prepare the DP table for the next state (after processing A[i]) std::vector<long long> next_dp = dp; // Initialize with current dp state counts. This represents subsequences *not* including A[i]. // Iterate through all current states idx from 0 to E-1 for (int idx = 0; idx < E; ++idx) { if (dp[idx] == 0) continue; // Skip states with zero count for efficiency // Calculate the index 'next_idx' of the state resulting from including A[i] long long current_state_val = idx; // Use a temporary variable for clarity int next_idx = 0; // Initialize index for the next state // Calculate components s'_k of the next state S' and combine them into next_idx for(int k=0; k<m; ++k) { // Extract k-th component s_k (current exponent for p_k) from current index idx // using integer division and modulo with the precomputed bases. int sk = (current_state_val / Bases[k]) % E_plus_1[k]; // Compute k-th component of the next state: s'_k = min(s_k + v'_k, e_k) int sk_prime = std::min(sk + V_prime[k], k_factors[k].e); // Accumulate s'_k into the flat index next_idx using base B_k next_idx += (long long)sk_prime * Bases[k]; } // Add the count dp[idx] (number of subsequences reaching state idx) // to the count of the computed next state index 'next_idx'. // This represents subsequences that *do* include A[i]. next_dp[next_idx] = (next_dp[next_idx] + dp[idx]) % MOD; } // Update the DP table for the next iteration using move semantics for potential efficiency gain. dp = std::move(next_dp); } // Calculate the index corresponding to the target state (e1, e2, ..., em) // This state represents products that are multiples of K. int target_idx = 0; for(int k=0; k<m; ++k) { target_idx += (long long)k_factors[k].e * Bases[k]; } // The final answer is the count stored in the target state dp[target_idx]. // Since K > 1, the target state is not the initial state (index 0), // so dp[target_idx] correctly counts only non-empty subsequences satisfying the condition. std::cout << dp[target_idx] << std::endl; return 0; }