HDU 5651 xiaoxin juju needs help A/B%C

题意:给一个字符串,每一个字符都要用上,问可以排成多少种不同的回文串。


想法:显然当每一个字母出现的次数都为偶数或者只有一个字母出现次数是奇数次时,一定可以组成回文串,其余的都是不可以的。因为回文串对称,所以我们只需要讨论一边的情况,假设一半的字符串长度是len,每一个字母出现的次数时cnt[],那么总情况数为len的阶乘,也就是A(len,len)这个很简单,但是会有重复的,因为对于相同的字符A(len,len)是把相同的字符也当成了不同的字符处理,所以会有很多是重复的。

因此A(len,len)/(cnt['a']*cnt['b']*...*cnt['z']);然后这个结果模一个mod。

现在问题就转化成了这个。怎么求看我的另一个文章:http://blog.csdn.net/triple_wdf/article/details/50994421


#include<stdio.h>
#include<string.h>
#define ll  long long
#define mod 1000000007
char s[1000+5];
int num[29];
ll lnv[29];
void extgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b)
    {
        x=1;
        y=0;
        return;
    }
    ll x1,y1;
    extgcd(b,a%b,x1,y1);
    x=y1;
    y=x1-(a/b)*y1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(num,0,sizeof(num));
        scanf("%s",s);
        int len=strlen(s);
        for(int i=0;i<len;i++)
        {
            num[s[i]-'a']++;
        }
        if(len==1)
        {
            printf("1\n");
            continue;
        }
        int nores=0;
        for(int i=0;i<26;i++)
        {
            if(num[i]%2==1) 
            {
                nores++;
            }
        }
        if(nores>1)
        {
            printf("0\n");
            continue;
        }
        len/=2;
        for(int i=0;i<26;i++)
        {
            ll x,y;
            lnv[i]=1;
            num[i]/=2;
            for(int j=1;j<=num[i];j++)
            lnv[i]=lnv[i]*j%mod;
            extgcd(lnv[i],mod,x,y);
            x=(x%mod+mod)%mod;
            lnv[i]=x;
        }
        ll res=1;
        for(int i=1;i<=len;i++)
        res=res*i%mod;
        for(int i=0;i<26;i++)
        {
            res=res*lnv[i]%mod;
        }
        printf("%lld\n",res%mod);
    }
    return 0;
}

 

 



你可能感兴趣的:(HDU 5651 xiaoxin juju needs help A/B%C)