結果

問題 No.937 Ultra Sword
ユーザー qwewe
提出日時 2025-05-14 13:10:56
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
WA  
実行時間 -
コード長 6,963 bytes
コンパイル時間 1,242 ms
コンパイル使用メモリ 92,432 KB
実行使用メモリ 15,692 KB
最終ジャッジ日時 2025-05-14 13:12:52
合計ジャッジ時間 3,909 ms
ジャッジサーバーID
(参考情報)
judge5 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 45 WA * 2
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <set>
#include <map>
#include <vector> // Ensure vector is included

// Define constants based on problem constraints
// Use a sufficiently large number for infinity if needed, but not required here
// const long long INF = 1e18; 
// Max value of A_i is 10^5, array size needs to be 100001 for 0-based indexing up to 100000
const int MAX_A_VAL = 100001; 

int N; // Number of monsters
std::vector<int> A; // Store initial HPs
int M = 0; // Maximum HP value encountered

std::vector<int> Basis; // Basis for the XOR span
std::set<int> L_V; // Set to store unique non-zero elements of the XOR span L(V)

/**
 * @brief Computes the basis of the vector space spanned by initial HPs under XOR operation.
 * Uses Gaussian elimination method.
 */
void build_basis() {
    // Basis stores the linearly independent elements under XOR
    std::vector<int> basis_temp;
    // Iterate through each initial HP value
    for(int x : A) {
        if (x == 0) continue; // Ignore HP=0, as A_i >= 1 per constraints
        // Reduce x by XORing with existing basis elements to find its unique contribution
        for(int b : basis_temp) {
            // If XORing with b reduces x, update x. Standard basis reduction step.
            x = std::min(x, x ^ b);
        }
        // If x is still > 0 after reduction, it means x adds a new dimension (is linearly independent)
        if (x > 0) {
            basis_temp.push_back(x);
            // Keep the basis sorted in descending order. This helps in reducing elements faster.
             std::sort(basis_temp.rbegin(), basis_temp.rend());
        }
     }
    Basis = basis_temp; // Assign the computed basis
}

/**
 * @brief Recursively generates all elements in the XOR span L(V) from the basis.
 * Stores unique non-zero generated values into the set L_V.
 * @param k Current index of the basis element being considered.
 * @param current_xor_sum The XOR sum accumulated so far.
 */
void generate_span(int k, int current_xor_sum) {
    // Base case: If we have considered all basis elements
    if (k == Basis.size()) {
        // Add the generated value to the set if it's non-zero
        if (current_xor_sum > 0) {
            L_V.insert(current_xor_sum);
        }
        return;
    }
    // Recursive step: Explore two possibilities for the k-th basis element
    // 1. Don't include the k-th basis element in the XOR sum
    generate_span(k + 1, current_xor_sum);
    // 2. Include the k-th basis element in the XOR sum
    generate_span(k + 1, current_xor_sum ^ Basis[k]);
}

// Using arrays for counts and Delta sum for efficiency
// Cnt[v] stores the number of monsters with HP v
int Cnt[MAX_A_VAL]; 
// Delta[K] stores the total HP reduction achieved by sacrificing K
// Delta[K] = sum over v=mK ( Cnt[v] * (v - v/K) )
long long Delta[MAX_A_VAL]; 

int main() {
    // Faster I/O operations
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    // Read input N
    std::cin >> N;
    A.resize(N); // Resize vector A to hold N elements
    long long S_total = 0; // Total initial HP sum, use long long for potentially large sums
    M = 0; // Reset max HP M
    
    // Read initial HPs, compute total sum S_total, find max HP M, and fill Cnt array
    for (int i = 0; i < N; ++i) {
        std::cin >> A[i];
        if (A[i] > M) {
            M = A[i]; // Update max HP
        }
        // Ensure HP is within bounds [1, MAX_A_VAL-1] before accessing Cnt array
        if (A[i] > 0 && A[i] < MAX_A_VAL) { 
             Cnt[A[i]]++; // Increment count for this HP value
        }
         S_total += A[i]; // Accumulate total HP
    }
    
    // Handle edge case M=0 (if N=0 or all A_i=0), ensure M >= 1 for array indexing and loops.
    // Based on constraints N>=2 and A_i>=1, M will be at least 1.
    if (M == 0) M = 1; 

    // Precompute Delta[K] for all K from 1 to M
    // This takes O(M log M) time using a harmonic series summation approach
    for (int K = 1; K <= M; ++K) {
        // Iterate through all multiples v of K up to M
        for (int v = K; v <= M; v += K) {
            // If there are monsters with HP v
            if (Cnt[v] > 0) {
                // Add the total reduction achieved for these monsters to Delta[K]
                // Reduction per monster is (v - v/K)
                Delta[K] += (long long)Cnt[v] * (v - v / K);
            }
        }
    }

    // Compute the XOR basis from initial HPs A
    build_basis();
    // If basis is not empty, generate all values in its XOR span L(V)
    if (!Basis.empty()) {
        // Start generating span from basis index 0 with initial XOR sum 0
        generate_span(0, 0); 
    }

    // Final candidate set C_final stores all possible values K for sacrifice
    std::set<int> C_final;
    // Add all initial HPs A_i to the candidate set
    for (int val : A) {
        if (val > 0) { // Ensure K > 0, as sacrifice value must be positive
            C_final.insert(val);
        }
    }

    // Add values generated by XOR span L(V) and its doublings (2^p * x)
    for (int x : L_V) {
        // Use long long for K to handle potential intermediate large values during doubling
        long long K_ll = x; 
        // Iterate through K = x, 2x, 4x, ... as long as K is positive and <= M
        while (K_ll > 0 && K_ll <= M) {
            C_final.insert((int)K_ll); // Add K to candidate set
             
             // Optimization: Check if doubling K would exceed M to avoid unnecessary work and potential overflow.
             // If K_ll > M/2, then 2*K_ll > M. Check K_ll != 0 to prevent infinite loop if M/2<0 (not possible here).
             if (K_ll > M / 2 && K_ll != 0) { 
                 break; // Stop doubling if next value will exceed M
             }
             if(K_ll == 0) break; // Safety break if somehow K becomes 0
            K_ll *= 2; // Double K for the next iteration
        }
    }

    // Calculate the minimum possible total HP after applying the best operation
    // Initialize minimum HP with the initial total HP (represents the case of performing no operation)
    long long min_total_hp = S_total; 
    
    // Iterate through all candidate K values in the final set
    for (int K : C_final) {
        // K must be a positive integer to be a valid sacrifice HP
        // Also K must be within bounds [1, M] to access Delta[K]
        if (K > 0 && K <= M) { // Check K > 0 and K <= M
           // The final HP sum after sacrificing K is S_total - Delta[K]
           min_total_hp = std::min(min_total_hp, S_total - Delta[K]);
        } 
        // Note: If K > M, Delta[K] would effectively be 0 because no A_i can be a multiple of K > M (since A_i <= M). 
        // The sum would be S_total. This case is already covered by initializing min_total_hp = S_total.
    }

    // Output the minimum total HP found
    std::cout << min_total_hp << std::endl;

    return 0;
}
0