1 条题解

  • 0
    @ 2026-4-3 13:10:57

    A. 樱子的考试 - 详细题解

    问题重述

    给定 aa11bb22,在每个数前添加正号或负号,问能否使整个数组的和为 00


    问题转化

    在每个数前添加 ++-,相当于将数组分成两个子集:

    • 带正号的数放入集合 PP
    • 带负号的数放入集合 NN

    数组总和为 00 等价于:

    xPx=xNx\sum_{x \in P} x = \sum_{x \in N} x

    而所有数的总和为:

    $$S = \sum_{x \in P} x + \sum_{x \in N} x = 2 \times \sum_{x \in P} x $$

    因此,总和 SS 必须是偶数,且每个子集的和为 S2\frac{S}{2}


    必要条件分析

    aa11bb22,则总和为:

    S=a×1+b×2=a+2bS = a \times 1 + b \times 2 = a + 2b

    条件 1:总和为偶数

    S=a+2ba(mod2)S = a + 2b \equiv a \pmod{2}

    所以 SS 为偶数当且仅当 aa 为偶数。

    结论:若 aa 是奇数,则直接输出 "NO"


    条件 2:能否凑出 S2\frac{S}{2}

    aa 为偶数时,设 a=2ka = 2k,则:

    $$\frac{S}{2} = \frac{a + 2b}{2} = \frac{2k + 2b}{2} = k + b $$

    我们需要判断能否用若干 1122 凑出 k+bk + b

    关键观察

    • 每个 22 可以看作两个 11 的替代
    • 我们实际上是在分配符号,等价于选择一部分数放在正号集合

    分类讨论

    情况 1:bb 为偶数

    bb 为偶数时,可以将 22 平均分成两组,每组 b2\frac{b}{2}22,和为 bb
    再加上 kk11 到正号集合,就能得到 k+bk + b

    结论bb 为偶数时,答案为 "YES"


    情况 2:bb 为奇数

    bb 为奇数时,无法将 22 完全平分。
    b=2m+1b = 2m + 1,则 S2=k+2m+1\frac{S}{2} = k + 2m + 1

    22 尽量平分:每组 mm22,和为 2m2m,还剩下一个 22 需要分配。

    这个剩下的 22 必须放在正号集合,此时正号集合的和为 2m+22m + 2,还需要 k1k - 111 来凑成 k+2m+1k + 2m + 1

    因此,需要至少 2211(因为 k1k \ge 1 才能有 k10k - 1 \ge 0,而 k=a2k = \frac{a}{2},所以 a2a \ge 2)。

    更简单的理解:

    • bb 为奇数时,总和为 a+2ba + 2b 是奇数?不对,aa 已经保证为偶数,所以总和是偶数
    • 但奇数个 22 意味着无法直接平分 22,需要用 11 来平衡
    • a=0a = 0,则没有 11 可以调整,答案为 "NO"
    • a2a \ge 2(即至少有两个 11),则可以用两个 11(和为 22)替代一个 22,实现平衡

    结论bb 为奇数时

    • a=0a = 0,答案为 "NO"
    • a2a \ge 2,答案为 "YES"

    算法步骤

    1. 读入 aa11 的个数)和 bb22 的个数)
    2. aa 为奇数,输出 "NO"
    3. 否则(aa 为偶数):
      • bb 为偶数,输出 "YES"
      • bb 为奇数:
        • a=0a = 0,输出 "NO"
        • 否则输出 "YES"

    完整代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        int t;
        cin >> t;
        
        while (t--) {
            int cnt1, cnt2;
            cin >> cnt1 >> cnt2;
            
            if (cnt1 % 2 == 1) {
                cout << "NO" << endl;
            } else {
                if (cnt2 % 2 == 0) {
                    cout << "YES" << endl;
                } else {
                    if (cnt1 == 0) {
                        cout << "NO" << endl;
                    } else {
                        cout << "YES" << endl;
                    }
                }
            }
        }
        
        return 0;
    }
    

    时间复杂度

    • 每个测试用例 O(1)O(1)
    • 总复杂度 O(t)O(t)

    示例验证

    aa bb aa 奇偶 bb 奇偶 条件 输出
    0 1 奇且 a=0a=0 NO
    3
    2 0 YES
    3 奇且 a2a \ge 2
    3 1 - NO

    与样例输出完全一致。

    • 1

    信息

    ID
    6325
    时间
    1000ms
    内存
    256MiB
    难度
    3
    标签
    递交数
    1
    已通过
    1
    上传者