Problem Description
As we all known, xiaoxin is a brilliant coder. He knew palindromic strings when he was only a six grade student at elementry school.
This summer he was working at Tencent as an intern. One day his leader came to ask xiaoxin for help. His leader gave him a string and he wanted xiaoxin to generate palindromic strings for him. Once xiaoxin generates a different palindromic string, his leader will give him a watermelon candy. The problem is how many candies xiaoxin’s leader needs to buy?
Input
This problem has multi test cases. First line contains a single integer T(T≤20) which represents the number of test cases.
For each test case, there is a single line containing a string S(1≤length(S)≤1,000).
Output
For each test case, print an integer which is the number of watermelon candies xiaoxin’s leader needs to buy after mod 1,000,000,007.
Sample Input
3
aa
aabb
a
Sample Output
1
2
1
Source
BestCoder Round #77 (div.2)
题意:给你N个字符,所有排列中,是回文串的排列有多少个(左右对称)
先看:n个元素的排列,n个元素有p种不同的元素,每种元素的个数分别是a1,a2,a3…ap;
所以排列的总数有两种表示方法
1.fact(n)/(fact(a1)*fact(a2)***fact(ap))
fact(n)为n的阶乘。。
我们得求出fact(a)的逆元。。及a*a^-1=1%mod;这样1/a=a^-1;所以上边的式子可写成fact(a)*fact(a1)^-1*fact(a2)^-1***fact(ap)^-1;
//a的逆元%n
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
if(a==0&&b==0) return -1;//无最大公约数
if(b==0){x=1;y=0;return a;}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
//*********求逆元素*******************
//ax = 1(mod n)
long long mod_reverse(long long a,long long n)
{
long long x,y;
long long d=extend_gcd(a,n,x,y);
if(d==1) return (x%n+n)%n;
else return -1;
}
//预处理出1-500的阶乘的逆元
//返回d=gcd(a,b);和对应于等式ax+by=d中的x,y
long long quipow(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans%mod;
}
//fact[i]的的逆元nv[i]
long long fac[505],inv[505];
void prepare() 阶乘逆元
{
fac[0]=fac[1]=1;
for(int i=2;i<=500;i++) fac[i]=fac[i-1]*i%mod;
inv[500]=quipow(fac[500],mod-2);
for(int i=500-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
2.out=c(sum,a1)*c(sum-a1,a2)*c(sum-a1-a2,a3)*c(sum-a1-a2–ap-1,ap);
所以预处理排列组合的结果,,
long long c[1005][1005];
void init()
{
c[1][1]=1;
for(int i=0;i<=1000;i++) c[i][0]=c[i][i]=1;
for(int i=2;i<=1000;i++)
{
for(int j=1;j<=i;j++)
{
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
}
最后贴上三种AC的代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define mod 1000000007
long long fact(int n){
long long out=1;
for(int i=1;i<=n;i++) out=out*i%mod;
return out;
}
//返回d=gcd(a,b);和对应于等式ax+by=d中的x,y
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
if(a==0&&b==0) return -1;//无最大公约数
if(b==0){x=1;y=0;return a;}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
//*********求逆元素*******************
//ax = 1(mod n)
long long mod_reverse(long long a,long long n)
{
long long x,y;
long long d=extend_gcd(a,n,x,y);
if(d==1) return (x%n+n)%n;
else return -1;
}
int main()
{
int T_T;
scanf("%d",&T_T);
getchar();
while(T_T--){
char a[1005];
int cnt[100];
memset(cnt,0,sizeof(cnt));
gets(a);
int len=strlen(a);
for(int i=0;i<len;i++){
cnt[a[i]-'a'+1]++;
}
bool huichuan=true;
int ji=0;
long long ans=1;
for(int i=1;i<=26;i++){
if(cnt[i]%2!=0){
if(ji!=0){
huichuan=false;
break;
}
ji++;
}
if(cnt[i]>0) ans=ans*mod_reverse(fact(cnt[i]/2),mod)%mod;
}
if(huichuan==true){
printf("%I64d\n",ans*fact(len/2)%mod);
}
else printf("0\n");
}
return 0;
}
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define mod 1000000007
//返回d=gcd(a,b);和对应于等式ax+by=d中的x,y
long long quipow(long long a,long long b)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans%mod;
}
//fact[i]的的逆元nv[i]
long long fac[505],inv[505];
void prepare() //阶乘逆元
{
fac[0]=fac[1]=1;
for(int i=2;i<=500;i++) fac[i]=fac[i-1]*i%mod;
inv[500]=quipow(fac[500],mod-2);
for(int i=500-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
int main()
{
int T_T;
scanf("%d",&T_T);
getchar();
prepare();
while(T_T--){
char a[1005];
int cnt[100];
memset(cnt,0,sizeof(cnt));
gets(a);
int len=strlen(a);
for(int i=0;i<len;i++){
cnt[a[i]-'a'+1]++;
}
bool huichuan=true;
int ji=0;
long long ans=1;
for(int i=1;i<=26;i++){
if(cnt[i]%2!=0){
if(ji!=0){
huichuan=false;
break;
}
ji++;
}
if(cnt[i]>0) ans=ans*inv[cnt[i]/2]%mod;
}
if(huichuan==true){
printf("%I64d\n",ans*fac[len/2]%mod);
}
else printf("0\n");
}
return 0;
}
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define mod 1000000007
long long c[1005][1005];
void init()
{
c[1][1]=1;
for(int i=0;i<=1000;i++) c[i][0]=c[i][i]=1;
for(int i=2;i<=1000;i++){
for(int j=1;j<=i;j++){
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
}
int main()
{
int T_T;
scanf("%d",&T_T);
getchar();
init();
while(T_T--){
char a[1005];
int cnt[100];
memset(cnt,0,sizeof(cnt));
gets(a);
int len=strlen(a);
for(int i=0;i<len;i++){
cnt[a[i]-'a'+1]++;
}
bool huichuan=true;
int ji=0;
long long ans=1;
for(int i=1;i<=26;i++){
if(cnt[i]%2!=0){
if(ji!=0){
huichuan=false;
break;
}
ji++;
}
int times=cnt[i]/2;
ans=ans*c[len/2][times]%mod;
len=len-cnt[i];
}
if(huichuan==true){
printf("%I64d\n",ans);
}
else printf("0\n");
}
return 0;
}
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I have a dream!A AC deram!!
orz orz orz orz orz orz orz orz orz orz orz
orz orz orz orz orz orz orz orz orz orz orz
orz orz orz orz orz orz orz orz orz orz orz
*/