题解:P10534 [Opoi 2024] 简谐振动

· · 题解

\begin{Bmatrix}\color{red}\LARGE\bold{Solution}\\\normalsize\texttt{No.009 }\bold{P10534}\end{Bmatrix}\times\footnotesize\texttt{ By Xyz105}

题目描述

已知一个数字串 S,请你判断是否存在一种长度为 n n 为奇数的整数序列 A_i,使得 A_1+A_2,A_2+A_3,\dots,A_{n-1}+A_n,A_n+A_1 的值按顺序依次拼接起来可以得到 S

特别的,如果存在一种方案使得拼接的时候两项中间用 [0,\infty)0 分隔仍然可以得到 S,该方案仍然合法。所有数据保证最前面没有前导 0

解题思路

不妨设分解 S 所得出的数字分别为 B_{1\ldots n}。因为最前面是没有前导 0 的,并且“两项中间用 [0,\infty)0 分隔”说明非开头的数字可以有前导 0,所以实际上 S 可以任意分解

考虑用 A_1 表示 A_{2\ldots n},有

A_1&B_1-A_1&B_2-B_1+A_1&\cdots&B_{n-1}-B_{n-2}+\cdots-B_1+A_1\cr +&+&+&+&+\cr B_1-A_1&B_2-B_1+A_1&B_3-B_2+B_1-A_1&\cdots&B_{n}-B_{n-1}+B_{n-2}-\cdots+B_1-A_1\cr ||&||&||&||&||\cr B_1&B_2&B_3&\cdots&B_n\end{matrix}

首尾相加的特性使得 B_{n}-B_{n-1}+B_{n-2}-\cdots+B_1-A_1=A_1

2A_1=B_{n}-B_{n-1}+B_{n-2}-\cdots+B_1,说明等号右边必须是偶数。

又因为对于任意正整数 k,都有 k-k 奇偶性相同,所以转为判定 B_{n}+B_{n-1}+B_{n-2}+\cdots+B_1 是偶数即可。

判断一个数是否为偶数,只需判断其个位即可。因此问题转化为 在 S 中取 n 个数(S 的最后一位必须取)使得它们相加为偶数。

可以循环 S 中每一位,记录奇数个数 \text{odd}、偶数个数 \text{even}。因为要保证“相加为偶数”,所以选取的奇数个数必须是偶数。因此记 \text{odd}' 为不大于 \text{odd} 的最大偶数,判断是否有 \text{odd}'+\text{even}\ge n 即可。

注意细节:S 的最后一位必须取。当 S 的末位是奇数时,应有 \text{odd}'>0n>1 才有可行方案。

参考代码

已经算较短了。

代码中 \text{odd}i1 表示,\text{odd}' 体现为 i1 / 2 * 2

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int MAXN = 1e6 + 10;

int t, n, l, i1, i2; char s[MAXN];

int main()
{
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%s", &n, s + 1), i1 = i2 = 0;
        for (int i = l = strlen(s + 1); i; i--) if (s[i] & 1) i1++; else i2++;
        puts(max(0, max(1, n - i1 / 2 * 2) - i2) || ((s[l] & 1) && (i1 == 1 || n == 1)) ? "No" : "Yes");
    }

    return 0;
}