hdu5651--A - xiaoxin juju needs help 组合数问题

来源:互联网 发布:网络消费者的心理特征 编辑:程序博客网 时间:2024/05/17 04:45
A - xiaoxin juju needs help
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status

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  which represents the number of test cases. 
For each test case, there is a single line containing a string 

Output

For each test case, print an integer which is the number of watermelon candies xiaoxin's leader needs to buy after mod 

Sample Input

3aaaabba

Sample Output

12

1

思路:乍一看感觉无从下手,但这是一道组合数的问题,在做这道之前要先明确一个知识点就是多重集的组合数,当n各不相同的物品全排列有n!中,当这n个物品包括n1个a1,n2个a2。。。时全排列应是n!/(n1!*n2!*n3!...)好了,开始分析题目,给出一个字符串,问这些字符最多可以组成多少种回文字符串,大体上将这些字符分成相同的两部分,然后全排列一部分就可以了,另一部分对衬出现,具体算法:1.统计字符串中各个字符出现的个数2.找字符出现次数为奇数的字符的个数,若大于1个则不能组成回文字符串3.讲所有字符出现个数除以2(将字符串分为相同的两部分)4.带入公式,ans=((len/2)!/(n1!*n2!*n3!..))%mod,这里出现了除法取余的情况,此时当然要求逆元了(不会不会吧!!!--扩展gcd)取x的最小正整数解带入公式注意!由于题目给额数据很大,所以要进行一些处理用递归打一个n!的表是不是很简单呢^@^

ac代码:

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int mod=1000000007;char a[1005];int b[100],c[100],tot;long long data[1010];void zhunbei()//打一个求n!的快速表{   data[0]=1,data[1]=1;   for(int i=2;i<=1005;i++)   {       data[i]=((data[i-1]%mod)*(i%mod))%mod;   }}long long gcd(long long a,long long b)//求逆元{    return b?gcd(b,a%b):a;}void exgcd(long long a,long long b,long long &x,long long &y){   if(b==0)   {       x=1;       y=0;       return ;   }   long long x1,y1;   exgcd(b,a%b,x1,y1);   x=y1;   y=x1-(a/b)*y1;}int main(){   zhunbei();    int T;    scanf("%d",&T);    getchar();    while(T--)    {      tot=0;      gets(a);      int len=strlen(a);      memset(b,0,sizeof(b));      for(int i=0;i<len;i++)//统计字符出现的个数      {          b[a[i]-'a']++;      }      int flag=0;      for(int i=0;i<100;i++)      {          if(b[i]%2)          {              flag++;          }          if(b[i]>0)          c[tot++]=b[i]/2;      }      if(flag>1)      {          printf("0\n");          continue;      }      long long ans=1;      for(int i=0;i<tot;i++)//求(n1!*n2!*n3!....)      {          ans=(ans*data[c[i]])%mod;      }      long long x,y;      exgcd(ans,mod,x,y);      x=x/gcd(ans,mod);      x=(x%mod+mod)%mod;//这两步是扩展gcd里边求最小正整数解      long long h=(data[len/2]*x)%mod;      printf("%lld\n",h);    }    return 0;}

0 0