开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情
【ICPC】2022济南站 E. Identical Parity | 数学
题目链接
题目
题目大意
定义序列的值是其中所有数字的和。
确定是否存在长度为 的排列,使得该排列中所有长度为 的子段的值具有相同的奇偶性。即判断是否存在长度为 的排列,使得其所有长度为 的子段和均为奇数,或者均为偶数。
排列的子段是该排列的连续子序列。
长度为 的排列是一个序列,其中从 到 的每个整数恰好出现一次。
思路
让我们对该题的题意进行一定的转化。
首先我们观察题目:
确定是否存在长度为 的排列,使得该排列中所有长度为 的子段的值具有相同的奇偶性。
我们是关心子段和的奇偶性,不关心具体的值。所以我们可以让排列里所有的数都对 取模,子段和的奇偶性不会发生改变。则原题变成了:
有一个长度为 的数组,在其中的 个位置上放 ,其他位置上放 。是否存在一种放置方案使得数组中所有长度为 的子段的值具有相同的奇偶性。
又因为是所有长度为 的区间,我们可以看做在长度为 的数组上有一个大小为 的框在滑动,框一开始框住了前 个元素,每往右移动一个位置,框内最左边的元素就会离开框,框外右边第一个元素就会进入框。框内元素的和奇偶性保持不变。
所以我们每移出框一个 ,就必须移入一个 。每移出一个 ,就必须移入一个 。即整个 数组有长度为 的循环节。
因为整个序列中应该有 个位置上是 ,有 个位置上是 ,所以我们希望每个循环节内的 和 数量之差尽可能小,即每 个元素的和是 。整个数组内有恰好 个完整的循环,则完整的循环的和是 。
因为每个循环内元素的和是 ,所以我们希望最后剩余的 的子段中 的数量可以多一点,来弥补每个循环内少放的 。
最后长度为 的子段中 的数量不能超过序列长度,也不能超过完整的循环中 的数量,所以最多能放 的数量为
所以最后长度为 的子段中最少要放 的数量是
所以整个数组中至少要放 的数量是
容易发现,只要整个数组中至少要放 的数量不超过 ,就一定可以通过调整最后的子段中 的数量使得整个数组中 的数量恰为 。
综上所述,
就输出 Yes,否则输出 No。
代码
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n, m;
scanf("%d%d", &n, &m);
if ((n+1)/2>=((m+1)/2)*(n/m)+n%m-min(n%m,m/2)) printf("Yes\n");
else printf("No\n");
}
int main()
{
int tt;
scanf("%d",&tt);
while (tt--) solve();
return 0;
}