hdu 5651 组合数学+费马小定理求逆元

来源:互联网 发布:类似whatsapp的软件 编辑:程序博客网 时间:2024/06/06 17:52

http://acm.hdu.edu.cn/showproblem.php?pid=5651
给定字符串,判断任意交换顺序,能产生几个回文串。
先判定0,如果有超过一个字母出现的次数那么就是不可能的。
求个数就是用排列组合了。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define M 1009typedef long long ll;char s[M];int num[26];const int mod = 1000000007;ll qpow(ll x,ll n,ll mod){    ll ans = 1;    while(n)    {        if(n & 1) ans = ans * x % mod;        x = x * x % mod;        n >>= 1;    }    return ans;}ll C(ll a,ll b){    ll s1 = 1, s2 = 1;    for(int i = b - a + 1;i <= b;i++) s1 = s1*i%mod;    for(int i = 1;i <= a;i++) s2 = s2*i%mod;    ll inv = qpow(s2,mod-2,mod);    return s1*inv%mod;    //return (s1%(s2*mod))/s2;}int main(){    ios::sync_with_stdio(false);    int T;    cin >> T;    while(T--)    {        cin >> s;        memset(num,0,sizeof(num));        int len = strlen(s);        for(int i = 0;i < len;i++) num[s[i] - 'a']++;        int sum = 0;        for(int i = 0;i < 26;i++)        {            if(num[i]&1) sum++;        }        if(sum > 1)        {            cout << 0 << endl;            continue;        }        ll ans = 1;        sum = len/2; //只看左半边        for(int i = 0;i < 26;i++)        {            if(!num[i]) continue;            if(num[i] & 1) num[i]--;            ans = ans*C(num[i]/2,sum)%mod;            sum -= num[i]/2; //已经放过的位置要减掉        }        cout << ans << endl;    }    return 0;}
0 0
原创粉丝点击