题解:P5684 [CSP-J2019 江西] 非回文串

传送门

一道很简单的数学题。。。

题目简化:给定一个字符串,通过交换顺序使它不是一个回文串。

看上去很简单,用一个大模拟就行了。

数据: 3 ≤ n ≤ 2000 3\le n\le 2000 3n2000

如果直接用模拟的话,时间复杂度就是 O ( n ! ) O(n!) O(n!),最坏情况下是 2000 ! 2000! 2000!

注意看题目中的这几个字:交换顺序。这说明了这个字符串中的字符是不会改变的,而题目要求我们求有多少种情况使得这个字符串不是回文串。

与回文串相关,立马想到回文串的对称性!

所以第一步一定是先统计每个字符出现了多少次(这里建议用 map)。

for(int i=1;i<=n;i++)
{
   
   
	cin>>c[i];
	mp[c[i]]++;//用mp来统计个数
}

因为回文串具有对称性,所以我们只需要考虑一边,另一边跟这边也就一样了。

直接求非回文串的个数太麻烦,这里用了正难则反的思路:我们只需要求出有多少个回文串,再用总的个数减掉就是答案了。

总的个数很好求,就是 n ! n! n!,那回文串的个数怎么求呢?

我们前面说过,考虑回文串只需要考虑一边就行了,所以说我们只需要将每种字符出现的次数 mp[c[i]]除以 2 2 2 就可以了。由此,我们需要将 mp[c[i]]分成两类。

mp[c[i]]为偶数时

此时 mp[c[i]]可以直接被分成两部分,总的 n n n 也一定是偶数。一边就有 n 2 \frac{n}{2} 2n 个字母,每个字母之间互相交换,一共有 n 2 ! \frac{n}{2}! 2n! 种情况。

现在我们又对于每个字母进行讨论。

因为字母之间是可以两两交换的,总的方案也就有 m p c i ! mp_{c_{i}}! mpci! 种但是同一边交换是没有用的啊,所以我们还要再这个基础上再去掉重复的,也就是同一边的搭配情况,算下来是 ( m p c i / 2 ) ! (mp_{c_{i}}/2)! (mpci/2)!

把上面的公式合在一起,我们就得到了一个字母的排列情况,即。

m p c i ! ( m p c i ) / 2 \frac{mp_{c_{i}}!}{(mp_{c_{i}})/2} (mpci

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值