[BZOJ3395]回文串

17 篇文章 0 订阅
9 篇文章 0 订阅
问题描述
有n( 1 ≤n≤ 4)种字母,第种字母有ai( 1 ≤ai≤ 10^ 9)个,你可以任意排列这些字母的顺序来组成一个字符串。你的任务是判断是否存在一种排列方式使得字符串中本质不同的回文子串的个数为n。

输入格式
每个输入文件包含多组数据。
输入文件的第一行只有一个正整数T( 1 ≤T≤ 10),表示数据的组数。
接下来依次输入T组数据。
每组数据的第一行,包含一个正整数n。
每组数据的第二行,包含n个正整数a1,a2, ··· ,an。

输出格式
对于每组输入数据依次输出一行答案,若存在输出YES,若不存在输出NO。

样例输入
1
4
2 2 5 5

样例输出
YES

样例解释
令s(l,r)表示字符串中下标从l到r的连续的一段,若 ∃l,r ,s ,s(l,r) = t,则称t是s的子串。
rev(s)表示字符串s的倒序,若s = rev(s),则称s是回文串。
若s ≠ t,则称s,t本质不同。
记这四种字母分别为a,b,c,d,字符串cdacdbcdacdbcd 的本质不同的回文子串共4个,分别是a,b,c,d,所以存在。


来源 by Quack


题解:
由题意可推得,当字符串中只有长度为1的回文子串(即单个字母)时,条件才成立。

知道这个条件,题就很好做了,直接分类讨论。

当n=1时,只有1种字母,其数量只能为1;

当n=2时,有2种字母,其数量只能各为1;

当n=3时,有3种字母,最多数量的字母和最少的之差不能超过1;

当n=4时,有4种字母。因为2个相同字母中间至少有2个不同的字母将其隔开(如abca),所以按数量排序,每次选大的三个,同时减去其中最小数的值,反复操作(其实也就2次)直到不为0的数≤2个,看其值是否≤1。


#include<cstdio>
#include<algorithm>
using namespace std;
int T, n, A[5];

int main() {
	for( scanf( "%d", &T ); T; T-- ) {
		scanf( "%d", &n ); for( int i=0; i<n; i++ ) scanf( "%d", &A[i] );
		if( n==1 ) A[0]==1 ? printf( "YES\n" ) : printf( "NO\n" );
		if( n==2 ) A[0]+A[1]==2 ? printf( "YES\n" ) : printf( "NO\n" );
		if( n==3 ) sort( A, A+n ), A[2]-A[0]<=1 ? printf( "YES\n" ) : printf( "NO\n" );
		if( n==4 ) {
			for( int i=0; i++<2; ) sort( A, A+n ), A[3]-=A[1], A[2]-=A[1], A[1]=0;
			A[2]<=1 && A[3]<=1 ? printf( "YES\n" ) : printf( "NO\n" );
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值