xiaoxin juju needs help
Accepts: 134
Submissions: 309
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
思路:如果说有大于1个的奇数字符存在,那么就不能构成回文。能构成的情况下,判断一半边就行了,另一个半边相同就行。然后就是组合数形式
#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#define ll __int64
#define MOD 1000000007
using namespace std;
char s[10009];
int num[1000];
//map<char,int>mp;
ll kuai(ll m,ll n)
{
ll b=1LL;
while(n)
{
if(n&1)
b=b*m%MOD;
n>>=1;
m=m*m%MOD;
}
return b;
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
scanf("%s",s);
int len=strlen(s);
if(len==1)
{
puts("1");
continue;
}
memset(num,0,sizeof num);
for(int i=0;i<len;i++)
{
num[s[i]]++;
}
int flag=0;
for(int i=0;i<256;i++)
{
if(num[i]%2) flag++;
}
if(flag>1)
{
puts("0");
continue;
}
int sum=0;
for(int i=0;i<256;i++)
{
num[i]/=2;
sum+=num[i];
}
ll ans=1;
for(int i=0;i<256;i++)
{
if(num[i] && sum>=num[i])
{
ll tmp=1LL;
ll tmp2=1LL;
int t=min(sum-num[i],num[i]);
int fff=sum;
for(int j=1;j<=t;j++)
{
tmp=tmp*fff%MOD;
fff--;
}
for(int j=1;j<=t;j++)
tmp2=tmp2*j%MOD;
tmp=tmp*kuai(tmp2,MOD-2)%MOD;//逆元把除法转乘法
sum-=num[i];
ans=(ans*tmp)%MOD;
}
}
printf("%I64d\n",ans);
}
return 0;
}