#43122: 解答


nagga300@gmail.com (nigger300)

學校 : 不指定學校
編號 : 289766
來源 : [210.71.2.39]
最後登入時間 :
2024-10-17 15:49:03
o638. B - 黃金題敘 -- 第二屆Chi怪壓常比賽 | From: [210.71.2.39] | 發表日期 : 2024-10-17 14:32

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 計算所有子集和
void countSubsetSums(const vector<long long>& nums, vector<long long>& sums) {
    int n = nums.size();
    int total = 1 << n; // 2^n

    for (int i = 0; i < total; ++i) {
        long long sum = 0;
        for (int j = 0; j < n; ++j) {
            if (i & (1 << j)) {
                sum += nums[j];
            }
        }
        sums.push_back(sum);
    }
}

int main() {
    int n;
    cin >> n;

    long long l, r;
    cin >> l >> r;

    vector<long long> nums(n);
    for (int i = 0; i < n; ++i) {
        cin >> nums[i];
    }

    // 將數組分為左右兩部分
    vector<long long> left(nums.begin(), nums.begin() + n / 2);
    vector<long long> right(nums.begin() + n / 2, nums.end());

    vector<long long> leftSums, rightSums;

    // 計算左部分和右部分的所有可能的和
    countSubsetSums(left, leftSums);
    countSubsetSums(right, rightSums);

    // 對右部分的和進行排序
    sort(rightSums.begin(), rightSums.end());

    long long result = 0;

    // 對於左部分的每一個和,找到右部分的匹配範圍
    for (long long sum : leftSums) {
        long long minRequired = l - sum;
        long long maxRequired = r - sum;

        // 使用 lower_bound 和 upper_bound 來查找範圍
        auto lowerBound = lower_bound(rightSums.begin(), rightSums.end(), minRequired);
        auto upperBound = upper_bound(rightSums.begin(), rightSums.end(), maxRequired);

        result += (upperBound - lowerBound);
    }

    cout << result << endl;

    return 0;
}

 
ZeroJudge Forum