题解 CF1109B Sasha and One More Name

先考虑Impossible的情况。

显然如果所有字符全一样那肯定无解。

还有一种情况就是 n 为奇数且除了中间的一个字符其余全部相等,也无解。

理由很简单,剩下的字符全相等,由于新串是回文的,所以和原来的串一定是同一个串。

下面我们分奇偶性来讨论。

  • n 为奇数

这种情况下,答案不大于 2 ,因为除了中间的旁边的字符不全相等,所以一定有中间的一段,他的两边不是回文串,直接切两下就行了。

同时,答案也不可能小于 2 ,因为如果一刀就行的话,由于新串回文,且长度为奇数,所以手动模拟一下就能看出,这样一定所有字符都相等才能让新串和原串全都回文,而这时答案为Impossible,不符合题意。

所以当 n 为奇数时,答案为 2

  • n 为偶数

这时稍微麻烦一点,分两种情况。

我们取串的前一半,由于是回文长度为偶数的串,所以后一半一样的不用管就可以了。

  1. 取出的这个串不是回文串,这时直接一刀把原串从中间分成两段即可,答案为 1
  2. 取出的串是回文串,这样我们可以把整个原串分成两半,因为这一半回文,所以求出当串长为 n2 时的答案。如果是 2 就对称的切一刀,原串答案仍为 2 。如果是 1 就还在那个位置切,原串答案仍为 1 。所以新串的答案即为原串的答案,递归处理即可。

时间复杂度 O(nlogn)

代码

Copy
#include<bits/stdc++.h> #define re register #define N 1001001 #define MAX 2001 #define inf 1e18 using namespace std; typedef long long ll; typedef double db; inline void read(re ll &ret) { ret=0;re ll pd=0;re char c=getchar(); while(!isdigit(c)){pd|=c=='-';c=getchar();} while(isdigit(c)){ret=(ret<<1)+(ret<<3)+(c&15);c=getchar();} ret=pd?-ret:ret; return; } ll t,n; char s[N]; signed main() { t=1; while(t--) { scanf("%s",s+1); n=strlen(s+1); re bool flag=true; for(re int i=2;i<=(n>>1);i++) flag&=(s[i]==s[i-1]); if(flag) { puts("Impossible"); continue; } start: flag=true; for(re int i=1;(i<<1)<=n;i++) { if(s[(n>>1)-i+1]!=s[i]) flag=false; } if(!flag&&(n&1)) { puts("2"); continue; } else if(!flag&&!(n&1)) { puts("1"); continue; } else if(flag&&(n&1)) { puts("2"); continue; } else if(flag&&!(n&1)) { n>>=1; goto start;//即为前文所说的递归,goto简化代码 } } exit(0); }
posted @   CelticOIer  阅读(153)  评论(6编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示