CF1604B 题解
CF1604B 题解
题面
题意
给定一个长度为 n 的数组 a,将 a 分成若干段,问是否有一种分段的方法使得每一段的最大上升子序列的长度的异或和为 0。
有多组数据。
前置知识
- 位运算,知道异或算法相同为假,不同为真,理解并能够运用 1⊕1=0。
- 数学归纳法(证明思路的时候会用到)。
思路(做法)
- 当 n 为偶数时,显然只需将 a 分成 n 段,每一段一个数字即可。这样每一段的最大上升子序列的长度为 1,且有偶数个段,因为 1⊕1=0,所以最终得到的结果也必为 0。
- 当 n 为奇数时,如果还是像上面这种简单粗暴的方法来构造的话,结果必定为 1(因为 n 为奇数)。所以就想到,要是有一个 i(i∈[1,n−1]),使得 ai⩽ai+1,的话,则把 ai,ai+1 放在一组,其余的一个数一组,这样的话,ai,ai+1 这一组的最大上升子序列的长度为 1,总共有偶数个 1 异或,则结果为 1。若不存在这样的 i,则无解。
思路正确性的证明
其实,上面的输出 YES
的方法不多说,不懂的话再看看题目,现在要证明为什么不存在 i(i∈[1,n−1]) 使得 ai⩽ai+1 的话就无解。
首先,我们知道,要是不存在这样的 i,则 a 为一个上升序列,所以不管怎么分段,分的那一段最大上升子序列的长度必定就为那一段的长度,那么就有以下证明:
引理:若有正整数 a,b,则 a⊕b 的结果的奇偶性与 a+b 的结果的奇偶性相同。
引理证明:
设 a,b 在二进制表达下的最后一位分别为 a′,b′(a′,b′∈{0,1}),则有以下两种情况:
- a′=b′,则由异或的运算规则,a⊕b 的结果为偶数,又由加法的运算规则,a+b 的结果也为偶数。所以两者奇偶性相同。
- a′≠b′,则由异或的运算规则,a⊕b 的结果为奇数,又由加法的运算规则,a+b 的结果也为奇数。所以两者奇偶性相同。
综上,a⊕b 的结果的奇偶性与 a+b 的结果的奇偶性相同。
证毕。
回到证明思路的正确性,咱们设每一段的最大上升子序列的长度为 b 数组,一共分成了 m 段。则 b1+b2+b3+⋯+bm=n 且为奇数。
由引理,b1⊕b2 奇偶性与 b1+b2 相同。
同理,(b1⊕b2)⊕b3 奇偶性与 (b1+b2)+b3 相同。(把 b1+b2 看成一个整体。)
由数学归纳法得,b1⊕b2⊕b3⊕⋯⊕bn 奇偶性与 b1+b2+b3+⋯+bm 相同。
所以,b1⊕b2⊕b3⊕⋯⊕bn 为奇数。
而 0 为偶数,所以这种情况必定输出 NO
。
证毕。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
long long T,n,a[100005];
bool flag;
int main(){
scanf("%lld",&T);//多组数据
while(T--){
flag=false;//初始化
scanf("%lld",&n);
if(n%2==0) flag=true;//直接可以
for(int i=0; i<n; i++){
scanf("%lld",&a[i]);
if(i&&a[i]<=a[i-1]) flag=true;//这也是可以的
}
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现