結果

問題 No.2313 Product of Subsequence (hard)
ユーザー qwewe
提出日時 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
権限があれば一括ダウンロードができます

ソースコード

diff #

#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;
}
0