传送门
xiaoxin巨从小就喜欢字符串,六年级的时候他就知道了什么是回文串。这时,xiaoxin巨说到:如果一个字符串 S 是回文串,那么该字符串从前往后看和从后往前看是一样一样的。
六年级的暑假,xiaoxin很快就做完了暑假作业,然后到腾讯做起了实习生。这日,leader给了xiaoxin一个字符串,请xiaoxin帮忙写一个函数来生成所有可能的回文串,可以任意改变字符串的顺序但是不可以扔掉某个字符。并且leader告诉xiaoxin,每生成一个不一样的回文串就可以得到一颗西瓜糖。
请你帮忙计算xiaoxin的leader最多需要买多少颗西瓜糖呢?
解题思路:
回文字符串的个数可以根据一个公式来推导一下:
条件:
1.len = strlen(str),len>>=1;
2.num[i]:表示的是字符串每个字符 - 'a' 的个数,然后将其除以2;
结果: ret = ((len/2)!)/(num[0]! * num[1]! * ... * num[25]!) MOD 1e9+7;
根据这个公式我们只需要求一下阶乘的逆元就行了,因为是取模的运算,所以我们一边乘一边取模,不会超long long,最后不要忘记的是,如果是负数要转化为正数在进行取模,最后就是乘起来就行了。。。
My Code:
#include
#include
#include
using namespace std;
typedef long long LL;
const int MOD = 1e9+7;
const int MAXN = 1e3+5;
char str[MAXN];
int num[28];
LL a[28];
void Ex_gcd(LL a, LL b, LL &x, LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
LL x1, y1;
Ex_gcd(b, a%b, x1, y1);
x = y1;
y = x1-(a/b)*y1;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>str;
int len = strlen(str);
memset(num, 0, sizeof(num));
for(int i=0; i= 2)
puts("0");
else
{
LL ret = 1;
len>>=1;
for(int i=0; i<26; i++)
{
LL x, y;
num[i]>>=1;
a[i] = 1;
for(int j=1; j<=num[i]; j++)
a[i] = a[i]*j%MOD;
Ex_gcd(a[i], MOD, x, y);
x = (x%MOD+MOD)%MOD;
a[i] = x;
}
for(int i=1; i<=len; i++)
ret = ret*i%MOD;
for(int i=0; i<26; i++)
ret = ret*a[i]%MOD;
printf("%lld\n",ret%MOD);
}
}
return 0;
}