题解:学而思编程 公平分配

【题目来源】

学而思编程:公平分配

【题目描述】

小猴和小美从猴博士那里得到 \(n\) 个糖果。每一颗糖果重 \(1\) 克或 \(2\) 克。现在他们想要公平地将糖果分成两组,使得两组糖果的重量(每一组糖果的重量之和)相等。他们想要你帮助判断糖果是否能恰好分成两组。

【输入】

输入第一行一个整数 \(t\),表示测试数据的组数。

接下来,每组数据第一行一个整数 \(n\) 表示两人收到的糖果数量。

接下来一行 \(n\) 个整数 \(w_1,w_2,\dots,w_n\),表示每颗糖果的重量。

【输出】

输出共 \(t\) 行。对于每组测试数据,如果可以分成重量相等的两组,则输出 YES,否则输出 NO。

【输入样例】

4
1
2
2
1 2
3
1 1 1
4
2 2 2 2

【输出样例】

NO
NO
NO
YES

【核心思想】

  1. 问题分析:给定 \(n\) 颗糖果,每颗重量为 \(1\) 克或 \(2\) 克,判断能否分成两组使重量相等。这是一个奇偶性分析问题,关键在于发现重量为 \(2\) 克的糖果不影响分组的奇偶约束,而重量为 \(1\) 克的糖果数量直接决定可行性。

  2. 算法选择

    • 奇偶不变性:分析两类糖果对分组奇偶性的不同影响
    • 计数判定:统计重量为 \(1\) 的糖果数量 \(cnt\),根据奇偶性直接判定
  3. 关键步骤

    • 读取输入:读取测试组数 \(t\)
    • 逐组处理(循环 \(t\) 次):
      • 读取糖果数量 \(num\)
      • 统计 \(1\) 克糖果:初始化 \(cnt = 0\),遍历 \(num\) 颗糖果:
        • \(w_j = 1\),则 \(cnt \leftarrow cnt + 1\)
        • 重量为 \(2\) 的糖果无需额外统计
      • 判定条件
        • \(cnt \bmod 2 = 0\)\(cnt \neq 0\)\(1\) 的个数为偶数且存在,输出 YES
        • 否则若 \((num - cnt) \bmod 2 = 0\)\(cnt = 0\):全是 \(2\) 且个数为偶数,输出 YES
        • 否则:输出 NO
  4. 时间/空间复杂度

    • 时间复杂度:\(O(t \times num)\),每组数据遍历 \(num\) 颗糖果
    • 空间复杂度:\(O(1)\),仅使用 \(cnt\) 计数器,无需存储数组
  5. 奇偶分析的核心思想

    • \(2\) 克糖果的消去性:重量为 \(2\) 的糖果无论分配到哪一组,对两组重量差的贡献都是偶数。偶数个 \(2\) 可均分,奇数个 \(2\) 无法均分(除非有 \(1\) 克糖果配合调整奇偶)
    • \(1\) 克糖果的决定性\(1\) 克糖果是改变重量奇偶性的唯一来源。设 \(1\) 克糖果有 \(cnt\) 个,\(2\) 克糖果有 \(num - cnt\) 个:
      • \(cnt = 0\)(全为 \(2\)):需 \(num\) 为偶数才能均分,每组 \(num/2\)\(2\) 克糖果
      • \(cnt > 0\)\(2\) 克糖果可任意均分(或放入同一组由 \(1\) 克糖果补偿),关键是 \(1\) 克糖果需为偶数才能均分
    • 简化判定:实际只需关注 \(1\) 克糖果的个数是否为偶数(且存在),或全为 \(2\) 时总数是否为偶数
    • 适用于重量约束下的分组问题、奇偶性判定类组合问题

【算法标签】

数学

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n;

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int num;
        cin >> num;  // 读取数字个数
        int cnt = 0;  // 统计值为1的个数
        for (int j = 1; j <= num; j++)
        {
            int w;
            cin >> w;
            if (w == 1)
            {
                cnt++;  // 统计1的个数
            }
        }
        // 判断条件1:如果1的个数是偶数且不为0
        if (cnt % 2 == 0 && cnt != 0)
        {
            cout << "YES" << endl;
        }
        // 判断条件2:如果没有1,但非1的数字个数是偶数
        else if ((num - cnt) % 2 == 0 && cnt == 0)
        {
            cout << "YES" << endl;
        }
        else
        {
            cout << "NO" << endl;
        }
    }
    return 0;
}

【运行结果】

4
1
2
NO
2
1 2
NO
3
1 1 1
NO
4
2 2 2 2
YES
posted @ 2026-07-05 16:10  团爸讲算法  阅读(6)  评论(0)    收藏  举报