题目
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
分析与解答
参考代码以及思路:
https://www.cnblogs.com/shentr/p/5349489.html
https://blog.csdn.net/fun_zero/article/details/50989103
真的十分奇怪,这题我用小费马求逆元,wrong answer。之前小费马求出来的都不用判断逆元的正负,我估计还是错在逆元的正负上了,最后改也没改出来,用欧几里得求逆元倒是求出来了
1.回文串的性质
给你n个字母,求可以组成的回文串的个数
1.1。形成回文串的条件
1.n为奇数,有一个字母的个数为奇数
2.n为偶数,字母个数全为偶数
所以回文串中最多仅有一个字母个数为奇数
满足这一条件才能够形成回文串
1.2。回文串的所有组成的可能情况
设回文串的长度为n,则左边的长度为n/2
由于回文串关于中点对称,所以只要满足形成回文串的条件,我们就只需找左边的所有可能情况,如果左边每个字母都是只出现一次,那么就是(n/2)!,但是这里可能有重复情况,那么就(n/2)!/(ni!nj! …),这里ni!中的ni是整个串中字符i出现的次数/2(因为是左边),这个是高中有重复排列的公式
2.求模
由于有除法,所以先求逆元,转换为乘法就ok了
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
int cnt[260];
char ch[1005];LL jiecheng(int n)//求阶乘
{if(n==0)return 1;LL ans=1;for(int i=1;i<=n;i++)ans=ans*i%MOD;return ans;
}LL x,y;
LL gcd(LL a,LL b)//欧几里得 需要找a的逆元,b是mod,x是最终求出的一个逆元
{LL t,d;if(b==0){x=1,y=0;return a;}d=gcd(b,a%b);t=x, x=y, y=t-(a/b)*y;return d;}int main()
{int t;cin>>t;while(t--){memset(cnt,0,sizeof(cnt));scanf("%s",ch);int len=strlen(ch);for(int i=0;i<len;i++){cnt[ch[i]-' ']++;}int count=0;for(int i=0;i<260;i++){if(cnt[i]&1)//如果是奇数就count++ count++;cnt[i]/=2;//只用左半部分 }if(count>1)//回文串中最多只能有一个字母的个数为奇数 {cout<<0<<endl;continue;}LL ans=jiecheng(len/2)%MOD;for(int i=0;i<260;i++){if(cnt[i]>0){gcd(jiecheng(cnt[i]),MOD);//依次求每个字符重复的个数得阶乘 if(x<0)x+=MOD;ans=ans*x%MOD;}}cout<<ans<<endl;}
}