题目大意
传送门
现在给你一个字符串,进行随机排序,求最后有多少种情况是回文串
思路
实际上,我们可以知道,如果奇数次出现的字符大于等于2个,那这个字符串就凉了。我们可以设每个字符的出现次数为 t o t [ i ] tot[i] tot[i],那么,就相当于求 ( t o t [ i ] > > = 1 ) (tot[i]>>=1) (tot[i]>>=1)组成的多重集的排列数,为什么呢?就相当于把字符串分成两半,两边一样,然后这个东西有个公式,叫做:对于一个多重集{ a 1 × s 1 , a 2 × s 2 , … … , a k × s k a_1\times s_1,a_2\times s_2,……,a_k\times s_k a1×s1,a2×s2,……,ak×sk},其中, s i s_i si是第i个元素, a i a_i ai是第i个元素的个数,则 a n s = n ! ∏ i = 1 k a i ! ans=\frac{n!}{\prod_{i=1}^{k}a_i!} ans=∏i=1kai!n!,其中, n = ∑ i = 1 k a i n=\sum_{i=1}^{k}a_i n=∑i=1kai,所以我们就可以直接算出来了
代码
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define Int register int
#define mod 1000000007
#define int long long
#define MAXX 1005
#define MAXN 30
int num[MAXN];
int inv[MAXX],fac[MAXX],inv_fac[MAXX];
string s;
void init()
{
fac[0] = inv[1] = inv_fac[1] = inv_fac[0] = 1;
for (Int i = 1;i <= 1000;++ i)
{
fac[i] = fac[i - 1] * i % mod;
if(i > 1)
{
inv[i] = inv[mod % i] * (mod - mod / i) % mod;
inv_fac[i] = inv_fac[i - 1] * inv[i] % mod;
}
}
}
int C(int n,int m)
{
if(n < m) return 0;
else if(n < 0 || m < 0) return 0;
else return fac[n] * inv_fac[m] % mod * inv_fac[n - m] % mod;
}
void read (int &x)
{
x = 0;char c = getchar();int f = 1;
while(c < '0' || c > '9'){if(c == '-')f = -f;c = getchar();}
while(c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + c - '0';c = getchar();}
x *= f;return ;
}
void write (int x)
{
if (x < 0){x = -x;putchar('-');}
if (x > 9) write (x / 10);
putchar (x % 10 + '0');
}
signed main()
{
init();
int times;
read (times);
while (times --)
{
memset (num,0,sizeof (num));
cin >> s;
int sum = 0;
bool flag = 1,cant = 1;
for (Int i = 0;i < s.length();++ i)
num[s[i] - 'a'] ++;
for (Int i = 0;i < 26;++ i)
{
if (num[i] % 2)
{
if (!flag)
{
cant = 0;
break;
}
flag = 0;
}
num[i] >>= 1;
sum += num[i];
}
if (!cant)
{
puts ("0");
continue;
}
int ans = fac[sum];
for (Int i = 0;i < 26;++ i)
ans = (ans * inv_fac[num[i]] % mod) % mod;
write (ans),putchar ('\n');
}
return 0;
}