题意:给你一个字符串,你可以任意重组他们的顺序,问可以出现多少个不同的回文串,答案对1e9+7取模。字符串长度小于等于1000.
题解:如果有多于一个的字符只出现奇数次的话,那么这个字符串肯定不可能组成回文串。否则的话,我们假设n为偶数,’a’有x个(x一定为偶数),那么’a’放进去的方案数为X[‘a’]=C(n/2,x/2),’b’有’y’个,那么X[‘b’]=C((n-x)/2,y/2),最后把所有字符的方案数乘起来便是答案,奇数的时候也是同理。
此题刚开始做的时候用了逆元,没有想到杨辉三角:C(n+1,i)=C(n,i)+C(n,i-1)
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
int count1[30];
char s[2001];
const ll MOD=1e9+7;
ll C[501][501];
int main(){
int _,n;
for(int i=0;i<=500;i++)
C[i][0]=1;
for(int i=1;i<=500;i++)
for(int j=1;j<=i;j++){
if(i==j)
C[i][i]=1;
else
C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
}
scanf("%d",&_);
while(_--){
mem0(count1);
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++)
count1[s[i]-'a']++;
int flag=0;
for(int i=0;i<=25;i++)
if(count1[i]&1)
flag++;
if(n%2==1&&(flag!=1)||(n%2==0&&flag!=0)){
printf("0\n");
continue;
}
ll ans=1;
if(n&1){
for(int i=0;i<=26;i++)
if(count1[i]!=0){
ans=ans*C[n/2][count1[i]/2]%MOD;
n-=count1[i];
}
}
else{
for(int i=0;i<=26;i++)
if(count1[i]!=0){
ans=ans*C[n/2][count1[i]/2]%MOD;
n-=count1[i];
}
}
printf("%lld\n",ans);
}
return 0;
}