HDU 5651 xiaoxin juju needs help

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5651


题意:给出一个字符串,可以打乱字符串的顺序,问可以有多少种方法使其成为回文串。


思路:先判断一下是否有奇数数量的字符,奇数长度的字符串最多有一个,偶数长度不能有奇数数量的字符。
然后我们去考虑半边的字符排列,也就是将所有的字符个数除2,然后在一半的位置上去求组合数相乘。
比如现在有4种字符,一共为a+b+c+d个。先去放第一个有C(a+b+c+d,a)种放法,继续放第二个,有C(b+c+d,b)....所有的数乘起来化简就是(a+b+c+d)!/a!/b!/c!/d!。取模除法可以转换为求逆元来解决,如果是模一个素数x,那么a的逆元为a^(x-2)。


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod 1000000007


char str[1009];
int T;
int t[30];
LL f[509];


void init()
{

    f[0] = 1;
    rep(i,1,500) f[i] = (i*f[i-1])%mod;
}

LL Pow( LL a , int b ) // a^b
{
    LL ans = 1;
    LL temp = a;
    while( b )
    {
        if ( b & 1 ) ans = ( ans * temp )% mod;
        temp = ( temp * temp )% mod;
        b>>=1;
    }
    return ans;
}

int main()
{
    init();
    cin>>T;
    getchar();
    while(T--)
    {
        gets(str);
        int len = strlen(str);
        Clean(t,0);
        rep(i,0,len-1) t[ str[i]-'a' ]++;
        int n = 0;
        int x = 0;
        rep(i,0,25)
        if ( t[i] > 0 )
        {
            n+=t[i]/2;
            if ( t[i] & 1 ) x++;
        }
        if ( ( len & 1 && x > 1 ) || ( !(len & 1) && x > 0 ) )
        {
            puts("0");
            continue;
        }
        LL ans = f[n];
        rep(i,0,25)
        {
            if ( t[i] > 1 )
            ans = ( ans * Pow( f[ t[i]/2 ] , mod-2 ) )% mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值