zoukankan      html  css  js  c++  java
  • HDU 5651 组合+逆元

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

    题目意思我看了半天没读懂,一直以为是回文子串又没看见substring的单词最后看博客才知道是用给出的字符任意组合。

    求不同的回文串个数,显然对于一个长度为奇数的串,我们可以枚举中间位置的元素,然后计算由剩余字符对半分(如果不可以就是零)之后的

    排列数就好了,由于有重复字符排列数公式也会不同,偶数串的话直接计算一次就好了。

    假设串长度为n,有m种不同元素,每种有ai个,则排列数就是    n!/(a1!*a2!*a3!*......am!)

    接着讨论具体计算过程,

    对于solve(),就是计算在当前合法状态下,对半分之后的排列总数对mod取余,公式就是

    len!/(a1!*a2!*a3!......*am!)%mod,由于阶乘值会很大所以只能用同余公式和逆元进行化简,

    ==> (1%mod*2%mod*....*len%mod)%mod*(1/a1!)%mod*(1/a2!)*......*(1/am!)%mod   //我们用fac[i]表示阶乘取模,prv[i]表示i!的逆对mod取模

    //对于1/x!%mod<==>1*(1/2)%mod*(1/3)%mod*...(1/x)%mod<==> 2-1%mod*3-1%mod......*x-1%mod

    ==>fac[i]*prv[a1]*prv[a2]*.....*prv[am]%mod;

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 LL mod=1e9+7;
     5 LL a[30];
     6 LL fac[1005]={1};
     7 LL inv[1005]={1,1};
     8 LL prv[1005]={1,1};
     9 LL solve(int len)
    10 {
    11     int i,j,k;
    12     LL res=fac[len];
    13     for(i=0;i<26;++i)
    14     {
    15         if(a[i]&1) return 0;
    16         a[i]/=2;
    17         res=res*prv[a[i]]%mod;
    18         a[i]*=2;
    19     }
    20     return res;
    21 }
    22 int main()
    23 {
    24     int t,i,j,n,m;
    25     char str[1005];
    26     for(LL i=1;i<=1000;++i) fac[i]=fac[i-1]*i%mod;
    27     for(i=2;i<=1000;++i) {
    28             inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    29             prv[i]=prv[i-1]*inv[i]%mod;
    30     }
    31     cin>>t;
    32     while(t--){memset(a,0,sizeof(a));
    33        scanf("%s",str);
    34        int len=strlen(str);
    35        for(i=0;i<len;++i){
    36         a[str[i]-'a']++;
    37        }LL ans=0;
    38        if(len&1){
    39         for(i=0;i<26;++i){
    40             if(!a[i]) continue;
    41             a[i]--;
    42             ans=(ans+solve((len-1)/2))%mod;
    43             a[i]++;
    44         }
    45        }
    46        else{
    47        ans=solve(len/2);
    48        }
    49        cout<<ans<<endl;
    50     }
    51     return 0;
    52 }
  • 相关阅读:
    清除缓存
    框架更新 (简)
    Xutils简
    动画
    夜间模式
    TabLoaout简单框架
    atomic原子类的理解
    单例模式中指令重排序及需要使用volatile的理解
    对volatile的理解
    jvm内存模型及垃圾回收GC
  • 原文地址:https://www.cnblogs.com/zzqc/p/7241068.html
Copyright © 2011-2022 走看看