HDU 5651xiaoxin juju needs help 带模除法逆元+有重复元素的全排列值

点击打开链接
xiaoxin巨从小就喜欢字符串,六年级的时候他就知道了什么是回文串。这时,xiaoxin巨说到:如果一个字符串 SSS 是回文串,那么该字符串从前往后看和从后往前看是一样一样的。

六年级的暑假,xiaoxin很快就做完了暑假作业,然后到腾讯做起了实习生。这日,leader给了xiaoxin一个字符串,请xiaoxin帮忙写一个函数来生成所有可能的回文串,可以任意改变字符串的顺序但是不可以扔掉某个字符。并且leader告诉xiaoxin,每生成一个不一样的回文串就可以得到一颗西瓜糖。

请你帮忙计算xiaoxin的leader最多需要买多少颗西瓜糖呢?

#include <iostream>
#include <cstring>
#include <cmath>
#include<cstdio>
#include<stack>
#include <queue>
#include <algorithm>
#include <set>
#include <map>
#define LL __int64
using namespace std;
char s[1010];
LL A[30];
LL B[1010];
LL J[1210]={1,1};
const LL MOD=1e9+7;
LL solve(LL x)       ///求带模除法逆元
{
    LL n=MOD-2;
    LL ans=1;
    while(n)
    {
        if(n&1)
        {
            (ans*=x)%=MOD;
        }
        (x*=x)%=MOD;
        n>>=1;
    }
    return ans;
}
int main()  ///利用白书 104页 有重复元素的全排列公式
             ///n1!*n2!*n3!*...*nk!*x=n!    x即为有重复元素的全排列值
{
    int t;
    for(LL i=2;i<1011;i++)
    {
        (J[i]=J[i-1]*i)%=MOD;
    }
  scanf("%d",&t);
  LL cnt;
  while(t--)
  {
      memset(A,0,sizeof(A));
      scanf("%s",s);
      int tmp=0;
      int len=strlen(s);
      for(int i=0;s[i];i++)
      {
          A[s[i]-'a']++;
      }
      if(len==1)
      {
          printf("1\n");
          continue;
      }
      cnt=0;
      for(int i=0;i<26;i++)
      {
           if(A[i]%2)
            tmp++;
      }
      for(int i=0;i<26;i++)
        cnt+=A[i]/2;
      if(tmp>1)
      {
          printf("0\n");
          continue;
      }
      LL ans=J[cnt];
      for(LL i=0;i<26;i++)
      {
          (ans*=(solve(J[A[i]/2])))%=MOD;
      }
      printf("%I64d\n",ans);
  }
    return 0;
}

你可能感兴趣的:(HDU 5651xiaoxin juju needs help 带模除法逆元+有重复元素的全排列值)