Technical Analysis of Xiangtan University Spring 2023 Freshman Programming Contest

Problem A: Strategic Allocation

This challenge involves selecting a subset of items to meet a weight capacity requirement with the minimum count. The optimal approach utilizes a greedy strategy. By prioritizing larger weights first, we minimize the number of items required to reach the target threshold.

void processAllocation() {
    int itemCount, capacityLimit;
    std::cin >> itemCount >> capacityLimit;
    
    std::vector<int> weights(itemCount);
    for(int i = 0; i < itemCount; ++i) {
        std::cin >> weights[i];
    }

    // Sort weights in descending order for greedy selection
    std::sort(weights.begin(), weights.end(), std::greater<int>());

    int currentLoad = 0;
    for(int i = 0; i < itemCount; ++i) {
        currentLoad += weights[i];
        if(currentLoad >= capacityLimit) {
            // Output the 1-based index of the last added item
            std::cout << (i + 1) << "\n";
            return;
        }
    }
}</int></int>

Problem B: Task Scheduling Optimization

In scenarios where tasks run on multiple resources with cooldown periods, the total time depends on the relationship between processing duration and rest intervals. If the cooldown is shorter then or equal to the execution time, parallelism is maximized, resulting in linear complexity. When the cooldown exceeds execution time, idle periods must be calculated based on the ratio of tasks.

void analyzeScheduling() {
    int duration, cooldown, totalTasks;
    std::cin >> duration >> cooldown >> totalTasks;

    if(duration <= cooldown) {
        // Cooldown doesn't limit throughput
        std::cout << (long long)cooldown * totalTasks << "\n";
    } else {
        // Calculate idle time added due to longer cooldown
        long long baseTime = (long long)cooldown * totalTasks;
        long long diff = duration - cooldown;
        
        // Adjust based on whether task count is odd or even
        if(totalTasks % 2 != 0) {
            baseTime += (totalTasks / 2) * diff;
        } else {
            baseTime += ((totalTasks / 2) - 1) * diff;
        }
        std::cout << baseTime << "\n";
    }
}

Problem C: Grouping Constraints

Determining feasible pairings requires analyzing the parity of group sizes and verifying primality of summed combinations. Generally, groups with even members allow flexible pairing. Special attention is needed when dealing with odd-sized groups combined with even-sized ones to satisfy sum conditions (specifically targeting sums greater than 2).

bool verifyPrime(int value) {
    if(value < 2) return false;
    if(value == 2) return true;
    for(long long i = 2; i * i <= value; ++i) {
        if(value % i == 0) return false;
    }
    return true;
}

void solvePairingLogic() {
    int groupA, groupB, groupC;
    std::cin >> groupA >> groupB >> groupC;

    // If total count is odd, pairing is impossible
    if((groupA + groupB + groupC) % 2 != 0) {
        std::cout << "P\n";
        return;
    }

    // All groups even allows perfect pairing
    if(groupA % 2 == 0 && groupB % 2 == 0 && groupC % 2 == 0) {
        std::cout << "R\n";
        return;
    }

    // Handle cases where single elements exist
    if((groupA == 1 && groupB == 1) || (groupA == 1 && groupC == 1) || 
       (groupB == 1 && groupC == 1)) {
        std::cout << "R\n";
        return;
    }

    // Verify if pairwise sums can form primes
    bool valid = (verifyPrime(groupA + groupB) && verifyPrime(groupA + groupC) && groupA > 0) ||
                 (verifyPrime(groupB + groupA) && verifyPrime(groupB + groupC) && groupB > 0) ||
                 (verifyPrime(groupC + groupA) && verifyPrime(groupC + groupB) && groupC > 0);

    std::cout << (valid ? "R" : "P") << "\n";
}

Problem D: Modular Summation Property

This problem leverages the mathematical property that within a prime modulus $p$, the set of integers $\{1, \dots, p-1\}$ contains distinct modular inverses. Consequently, the summation logic simplifies to calculating the direct sum of the range $[1, p-1]$ rather than computing individual inverse operations.

void calculateModularSum() {
    int limit;
    std::cin >> limit;
    
    long long runningSum = 0;
    for(int i = 1; i < limit; ++i) {
        runningSum += i;
    }
    std::cout << runningSum << "\n";
}

Problem E: Numerical String Conversion

Converting numerical strings into localized units requires careful parsing of digit positions. The algorithm iterates through the input string, identifying zeros and non-zero digits to apply appropriate scale factors (representing thousands or millions). Zero handling must prevant redundant unit prefixes.

void convertNumberString() {
    std::string inputNum;
    std::cin >> inputNum;
    
    if(inputNum == "0") {
        std::cout << inputNum << "\n";
        return;
    }

    std::string resultUnit = "";
    const char* placeValues[] = {"", "T", "B", "K", "W", "Y"};
    const char* digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
    
    int len = inputNum.length();
    int i = 0;
    
    while(i < len) {
        int posFromRight = len - i - 1;
        int modIndex = posFromRight % 4;
        bool flagWei = false;
        bool flagYi = false;
        
        if(inputNum[i] == '0') {
            // Logic to handle consecutive zeros and skipped units
            int zeroSeq = 0;
            while(i < len && inputNum[i] == '0') {
                i++;
                if(posFromRight == 8 && !flagYi) {
                    resultUnit += "Y";
                    flagYi = true;
                }
                if(posFromRight == 4 && !flagWei && resultUnit.back() != 'Y') {
                    resultUnit += "W";
                    flagWei = true;
                }
                zeroSeq++;
            }
            
            if(posFromRight == 4 && !flagWei) resultUnit += "W";
            if(posFromRight == 8 && !flagYi) resultUnit += "Y";
            
            if(zeroSeq >= 1 && i < len && posFromRight != 4 && posFromRight != 8) {
                resultUnit += '0';
            }
        } else {
            resultUnit += digits[inputNum[i] - '0'];
            resultUnit += placeValues[modIndex];
            
            if(posFromRight == 4 && !flagWei) {
                resultUnit += "W";
                flagWei = true;
            } else if(posFromRight == 8 && !flagYi) {
                resultUnit += "Y";
                flagYi = true;
            }
            i++;
        }
    }
    std::cout << resultUnit << "\n";
}

Problem H: Equal Frequency Substrings

To identify substrings containing balanced occurrences of three specific characters, we utilize a cumulative frequency map. By tracking the difference between character counts as we iterate, repeated difference pairs indicate valid sub-ranges where the net change in relative frequency is zero.

void countBalancedSubstrings() {
    std::string s;
    std::cin >> s;

    long long validCount = 0;
    int countX = 0, countT = 0, countU = 0;
    std::map<:pair>, int> freqMap;
    
    // Initialize map with baseline difference pair
    freqMap[{0, 0}] = 1;

    for(size_t i = 0; i < s.size(); ++i) {
        if(s[i] == 'X') countX++;
        else if(s[i] == 'T') countT++;
        else if(s[i] == 'U') countU++; // Assuming 'U' for third char
        
        // Store relative differences between counts
        int diffXT = countX - countT;
        int diffUT = countU - countT;
        
        // Check if absolute counts are equal
        if(countX == countT && countT == countU) {
            validCount++;
        }
        
        // Add occurrences of previous states with same differences
        if(freqMap.count({diffXT, diffUT})) {
            validCount += freqMap[{diffXT, diffUT}];
        }
        
        freqMap[{diffXT, diffUT}]++;
    }
    
    std::cout << validCount << "\n";
}</:pair>

Tags: competitive-programming cpp algorithms number-theory string-processing

Posted on Sat, 27 Jun 2026 16:02:21 +0000 by mattpointblank