xiaoxin juju needs help
Accepts: 150
Submissions: 966
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
xiaoxin巨从小就喜欢字符串,六年级的时候他就知道了什么是回文串。这时,xiaoxin巨说到:如果一个字符串 S 是回文串,那么该字符串从前往后看和从后往前看是一样一样的。
六年级的暑假,xiaoxin很快就做完了暑假作业,然后到腾讯做起了实习生。这日,leader给了xiaoxin一个字符串,请xiaoxin帮忙写一个函数来生成所有可能的回文串,可以任意改变字符串的顺序但是不可以扔掉某个字符。并且leader告诉xiaoxin,每生成一个不一样的回文串就可以得到一颗西瓜糖。
请你帮忙计算xiaoxin的leader最多需要买多少颗西瓜糖呢?
输入描述
多组测试数据。第一行包含一个整数 T(T≤20) 表示组数。每组测试数据给出一个只包含小写字母的字符串 S(1≤length(S)≤1,000)
输出描述
对于每组测试数据,输出一个数, 表示leader需要买的西瓜糖的个数,结果对 1,000,000,007 取模。
输入样例
3 aa aabb a
输出样例
1 2 1
看见%1000000007很眼熟啊~
分析:
只有当字符串中的每个字母总数为奇数的个数不大于1时才能组成回文数;
若能够组成回文数,只需要求出其一半的字母所能组成的字符串的个数即为回文数个数;
只有当字符串中的每个字母总数为奇数的个数不大于1时才能组成回文数;
若能够组成回文数,只需要求出其一半的字母所能组成的字符串的个数即为回文数个数;
例如:字符串aaabbccccdddddd
总数为奇数的字母只有a,能组成回文串
将其分解为(abccddd) a (abccddd)
由对称性可知只要求出字符串abccddd的组合数即可,
即结果= C(7,1)*C(6,1)*C(5,2)*C(3,3) %1000000007
问题转换成了求组合数问题
组合数取模打表即可,详见代码:
总数为奇数的字母只有a,能组成回文串
将其分解为(abccddd) a (abccddd)
由对称性可知只要求出字符串abccddd的组合数即可,
即结果= C(7,1)*C(6,1)*C(5,2)*C(3,3) %1000000007
问题转换成了求组合数问题
组合数取模打表即可,详见代码:
#include<iostream>
#include<cstdio>
#include <cstring>
using namespace std;
int cmob[1005][1005];//用于保存组合数值cmob[m][n]即代表C(M,N)
int ccmob(){//函数迭代求值
int i,j;
cmob[0][0] = 1;
for(int i = 0;i < 1005;i++) {
cmob[i][1] = i;
cmob[i][0] = 1;
}
for(int i = 2;i < 1001;i++) {
for(int j = 1;j <= i;j++) {
cmob[i][j] = (cmob[i-1][j-1] + cmob[i-1][j]) % 1000000007;//取余可保证不溢出同时计算题目结果
}
}
}
int main()
{
ccmob();
int t,n,temp,flag,sum,k,ans;
string st;
int num[30],tp[30];//num用来保存每个字母出现的次数,tp用来保存出现过的字母的个数的一半,用于计算一半字母的组合数(不需要知道是哪个字母)
cin >> t;
while(t--) {
k = sum = flag = 0;
ans = 1;
for(int j = 0;j < 30;j++) {
num[j] = 0;
tp[j] = 0;
} //初始化数组与变量
cin >> st;
for(int i = 0;i < st.length();i++) {//统计每个字母出现的次数
num[st.at(i) - 97]++;
}
for(int j = 0;j < 26;j++) {
if(num[j] != 0) {
sum += num[j] / 2;//sum为一半的字母数
if(num[j] % 2 == 1) flag ++;//flag用来统计总数为奇数的字母个数超过1个则无解
if (flag > 1) {
cout << "0" << endl;
break;
}
tp[k++] = num[j] / 2;//保存分出的那一半的每个字母的个数
}
}
if(flag < 2){//当有解的时候
for(int j = 0;j < k - 1;j++) {//将C(SUM,TP[J])累乘即得结果,注意sum值要减去已经算过的
ans *= cmob[sum][tp[j]];
sum-=tp[j];
}
cout << ans << endl;
}
}
return 0;
}