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;
}