(回文串全排列个数) xiaoxin juju needs help

题目

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
#include
#include
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' ']++;
        }
        int count=0;
        for(int i=0;i<260;i++)
        {
            if(cnt[i]&1)//如果是奇数就count++ 
                count++;
            cnt[i]/=2;//只用左半部分 
        }
        if(count>1)//回文串中最多只能有一个字母的个数为奇数 
        {
            cout<<0<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<

你可能感兴趣的:(acm练习(c++/c))