Codeforces Round #640 (Div. 4) B. Same Parity Summands

Codeforces Round #640 (Div. 4)

翻译 岛田小雅

B. Same Parity Summands

出题人 MikeMirzayanov

有两个数 \(n\) \((1≤n≤10^9)\)\(k\) \((1≤k≤100)\)\(n\) 表示 \(k\) 个相同奇偶性(除以 \(2\) 余数相同)的正整型的和。

换种说法,我们需要找到一组 \(a_1,a_2,…,a_k\) 使得 \(a_i>0\) 恒成立,且使 \(n=a_1+a_2+…+a_k\),且 \(a_i\) 拥有唯一奇偶性。

答案可能不存在。

输入格式

第一行是一个整型 \(t\) \((1≤t≤1000)\),代表测试点个数。接下来是 \(t\) 个测试点,一行一个。

每个测试点由两个正整数组成,分别是 \(n\) \((1≤n≤10^9)\)\(k\) \((1≤k≤100)\)

输出格式

对每个测试点:

  • 如果答案存在,那么输出 YES 和一组 \(a_i\)
  • 如果答案不存在,就输出 NO

样例输入

8
10 3
100 4
8 7
97 2
8 8
3 10
5 3
1000000000 9

样例输出

YES
4 2 4
YES
55 5 5 35
NO
NO
YES
1 1 1 1 1 1 1 1
NO
YES
3 1 1
YES
111111110 111111110 111111110 111111110 111111110 111111110 111111110 111111110 111111120

题解

作者 岛田小雅

根据样例,很容易就能想到把 \(n\) 平均分成 \(k\) 份,然后把剩下的数字 \(r\) 加到分出来的 \(k\) 个加数上。

为了方便描述,我们令 \(div=\lfloor\frac{n}{k}\rfloor\)\(r=n \bmod k\)

这样一来,当 \(r\) 是偶数的时候,直接把 \(r\) 加在任意一个加数上就能得到答案。但由于一个数加上一个奇数时,它的奇偶性一定会被改变。所以当 \(r\) 是个奇数的时候,这种方法会导致加数的奇偶性不同,怎么办呢?

有很多种处理方法,这里我列举一个。我们还是把 \(r\) 全部加在一个加数上,这样就得到了 \(1\)\(div+r\)\(k-1\)\(div\),它们的奇偶性不同。为了让它们相同,我们必须改变 \(k-1\)\(div\) 的奇偶性。如果 \(k-1\) 是偶数,那么我们可以把每个 \(div\) 减去 \(1\),得到一个 \(k-1\)\(k-1\)\(div-1\)。然后把这个 \(k-1\) 加在其中一个 \(div-1\) 上,这样最后的答案就是 \(1\)\(div+r\)\(1\)\(div+k-2\)\(k-2\)\(div-1\),它们的奇偶性是相同的。如果 \(k-1\) 是奇数,则答案不存在。需要注意的是,这种方法得到的答案必须都是正整数,所以 \(div-1>0\)\(div+k-2>0\) 必须成立。

如果 \(n\) 不足以被分成 \(k\) 份,那么答案肯定不存在。

如果你习惯用逐位与来判断一个数的奇偶性,请一定要加括号,不然会 WA,别问我怎么知道的:(

详情见 C++ 运算符优先级

AC 代码

作者 岛田小雅
#include <bits/stdc++.h>
using namespace std;

int t, n, k;
int a, r;

int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> t;
    while(t--)
    {
        cin >> n >> k;
        if(k > n) goto NO;
        if((k&1)==0 && n&1) goto NO; // 如果n是奇数但k是偶数,那么答案必然不存在,因为偶数个奇数的和是偶数,偶数个偶数的和也是偶数。当然这一条不加也是对的。
        a = n/k, r = n%k;
        if(r&1 && (a-1<=0||a+k-2<=0)) goto NO;
        YES: cout << "YES" << '\n';
        if(r&1)
        {
            cout << a+r << ' ' << a+k-2;
            for(int i = 1; i <= k-2; i++) cout << ' ' << a-1; cout << '\n';
        }
        else
        {
            cout << a+r;
            for(int i = 1; i < k; i++) cout << ' ' << a; cout << '\n';
        }
        continue;
        NO: cout << "NO" << '\n';
    }
    return 0;
}
posted @ 2022-09-18 18:47  岛田小雅  阅读(14)  评论(0编辑  收藏  举报