hdu 5651 xiaoxin juju needs help 逆元 两种求解方式

xiaoxin juju needs help

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1159    Accepted Submission(s): 335


Problem Description
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(T20) which represents the number of test cases.
For each test case, there is a single line containing a string S(1length(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
 
Source
题意:给你一个字符串,判断有多少种方式使得这个字符串回文;
思路:先判断0的情况,其次标记26个字母,ans=c(len/2,a/2)*c(len-a/2,b/2)*c(len/2-a/2-b/2,c/2)......;
     因为在求组合数需要取模,所以需要利用逆元的方式求解;
     逆元详解:http://blog.csdn.net/acdreamers/article/details/8220787
   扩张欧几里德求解逆元
   第二个是用费马小定理求逆元
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll __int64
#define mod 1000000007
int scan()
{
    int res = 0 , ch ;
    while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
    {
        if( ch == EOF )  return 1 << 30 ;
    }
    res = ch - '0' ;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
        res = res * 10 + ( ch - '0' ) ;
    return res ;
}
char a[1010];
ll flag[30];
void extend_Euclid(ll a, ll b, ll &x, ll &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return;
    }
    extend_Euclid(b, a % b, x, y);
    ll tmp = x;
    x = y;
    y = tmp - (a / b) * y;
}
ll combine1(ll n,ll m) //计算组合数C(n,m)
{
    ll sum=1; //线性计算
    for(ll i=1,j=n;i<=m;i++,j--)
    {
        sum*=j;
        sum%=mod;
        ll x,y;
        extend_Euclid(i,mod,x,y);
        sum*=(x%mod+mod)%mod;
        sum%=mod;
    }
    return sum;
}
int main()
{
    ll x,y,z,i,t;
    scanf("%I64d",&z);
    while(z--)
    {
        memset(flag,0,sizeof(flag));
        scanf("%s",a);
        x=strlen(a);
        for(i=0;i<x;i++)
        flag[a[i]-'a']++;
        ll sum=0;
        for(i=0;i<26;i++)
        {
            if(flag[i]%2)
            sum++;
        }
        if(x%2==0&&sum)
        printf("0
");
        else if(x%2==1&&sum>1)
        printf("0
");
        else
        {
            ll f=x/2;
            ll ans=1;
            for(i=0;i<26;i++)
            {
                if(flag[i]/2)
                {
                    ans*=combine1(f,flag[i]/2);
                    f-=flag[i]/2;
                    ans%=1000000007;
                }
            }
            printf("%I64d
",ans);
        }
    }
    return 0;
}
View Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll __int64
#define mod 1000000007
int scan()
{
    int res = 0 , ch ;
    while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
    {
        if( ch == EOF )  return 1 << 30 ;
    }
    res = ch - '0' ;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
        res = res * 10 + ( ch - '0' ) ;
    return res ;
}
char a[1010];
ll flag[30];
ll poww(ll a,ll n)//快速幂
{
   ll r=1,p=a;
   while(n)
   {
       if(n&1) r=(r*p)%mod;
       n>>=1;
       p=(p*p)%mod;
   }
   return r;
}
ll combine1(ll n,ll m) //计算组合数C(n,m)
{
    ll sum=1; //线性计算
    for(ll i=1,j=n;i<=m;i++,j--)
    {
        sum*=j;
        sum%=mod;
        sum*=poww(i,1000000005);
        sum%=mod;
    }
    return sum;
}
int main()
{
    ll x,y,z,i,t;
    scanf("%I64d",&z);
    while(z--)
    {
        memset(flag,0,sizeof(flag));
        scanf("%s",a);
        x=strlen(a);
        for(i=0;i<x;i++)
        flag[a[i]-'a']++;
        ll sum=0;
        for(i=0;i<26;i++)
        {
            if(flag[i]%2)
            sum++;
        }
        if(x%2==0&&sum)
        printf("0
");
        else if(x%2==1&&sum>1)
        printf("0
");
        else
        {
            ll f=x/2;
            ll ans=1;
            for(i=0;i<26;i++)
            {
                if(flag[i]/2)
                {
                    ans*=combine1(f,flag[i]/2);
                    f-=flag[i]/2;
                    ans%=1000000007;
                }
            }
            printf("%I64d
",ans);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/jhz033/p/5330705.html