zoukankan      html  css  js  c++  java
  • 组合数相关问题

    http://blog.csdn.net/acdreamers/article/details/8037918

    上面的是lucas的讲解 感觉好清晰

    除以 阶乘就等于乘以逆元 当然 mod是素数

    lucas 就有如此应用

    上个例题吧

    HDOJ——5651

    这个题 果组合数死 可以用杨辉三角和lucas过

    ll com(ll n,ll m) //计算组合数C(n,m)
    {
        ll sum=1; //线性计算
        for(ll i=1,j=n;i<=m;i++,j--)
            sum=(sum*j)/i;
        return sum;
    } 
    超简陋的组合数代码

    杨辉三角AC代码

    #include<cstdio>
    #include<map>
    #include<vector>
    #include<stack>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<cstdlib> 
    #include<climits>
    #define PI acos(-1.0)
    #define INF 0x3fffffff
    using namespace std;
    typedef __int64 ll;
    typedef __int64 int64;
    const ll MOD=1e9+7;
    const int64 Mod=1e9+7;
    const double eps=1e-9;
    const int N=32768;
    const int MAXN=200000;
    typedef int rl; 
    inline void r(rl&num){
        num=0;rl f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
        num*=f;
    }    
    int c[1010][1010];
    char ch[1010];
    int a[27];
    int main(){
        for(int i=0;i<1010;i++)
        {
            c[i][i]=c[i][0]=1;
        }
        for(int i=0;i<1010;i++)
        {
            for(int j=1;j<=i;j++)
            {
                c[i][j]=(c[i-1][j-1]+c[i-1][j])%Mod; 
            }
        }
        int T;
        r(T);
        while(T--){
            scanf("%s",ch);
            int len=strlen(ch);
            for(int i=0;i<len;i++)
            {
                 a[ch[i]-'a']++;
            }
            int sum=0,s=0;
            for(int i=0;i<26;i++)
            {
                if(a[i]&1){
                    a[i]--;
                    sum++;
                }
                if(a[i]){
                    s++;
                }
            }
            if(sum>1){
                printf("0
    ");
            }
            else{
                if(s==0||s==1){
                    printf("1
    ");
                }
                else{
                    len=(len-sum)/2;
                    int64 x=1;
                    for(int i=0;i<26&&s>1;i++)
                    {
                        if(a[i]){
                            s--;
                            x*=c[len][a[i]/2];
                            len-=a[i]/2;
                            x%=Mod;
                        } 
                    }
                    printf("%I64d
    ",x);
                }
            }
            memset(a,0,sizeof(a));
        }
        return 0;
    }
    杨辉三角代码

    改动一点 但是死了

    #include<cstdio>
    #include<map>
    #include<vector>
    #include<stack>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<cstdlib> 
    #include<climits>
    #define PI acos(-1.0)
    #define INF 0x3fffffff
    using namespace std;
    typedef __int64 ll;
    typedef __int64 int64;
    const ll MOD=1e9+7;
    const int64 Mod=1e9+7;
    const double eps=1e-9;
    const int N=1e3+10;
    const int MAXN=200000;
    typedef int rl; 
    inline void r(rl&num){
        num=0;rl f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
        num*=f;
    } 
    ll f[N];
    void init(int p) {                 //f[n] = n!
        f[0] = 1;
        for (int i=1; i<=p; ++i) f[i] = f[i-1] * i % p;
    }
      
    ll pow_mod(ll a, ll x, int p)   {
        ll ret = 1;
        while (x)   {
            if (x & 1)  ret = ret * a % p;
            a = a * a % p;
            x >>= 1;
        }
        return ret;
    }
    ll Lucas(ll n, ll k, int p) {       //C (n, k) % p
         ll ret = 1;
         while (n && k) {
            ll nn = n % p, kk = k % p;
            if (nn < kk) return 0;                   //inv (f[kk]) = f[kk] ^ (p - 2) % p
            ret = ret * f[nn] * pow_mod (f[kk] * f[nn-kk] % p, p - 2, p) % p;
            n /= p, k /= p;
         }
         return ret;
    } 
    char ch[1010];
    int a[27];
    int main(){
        int T;
        init(N-1);
        r(T);
        while(T--){
            scanf("%s",ch);
            int len=strlen(ch);
            for(int i=0;i<len;i++)
            {
                 a[ch[i]-'a']++;
            }
            int sum=0,s=0;
            for(int i=0;i<26;i++)
            {
                if(a[i]&1){
                    a[i]--;
                    sum++;
                }
                if(a[i]){
                    s++;
                }
            }
            if(sum>1){
                printf("0
    ");
            }
            else{
                if(s==0||s==1){
                    printf("1
    ");
                }
                else{
                    len=(len-sum)/2;
                    int64 x=1;
                    for(int i=0;i<26&&s>1;i++)
                    {
                        if(a[i]){
                            s--;
                            x*=Lucas(len,a[i]/2,Mod);
                            len-=a[i]/2;
                            x%=Mod;
                        } 
                    }
                    printf("%I64d
    ",x);
                }
            }
            memset(a,0,sizeof(a));
        }
        return 0;
    }
    暂时不知道哪里wa

    问了利文学长后 改为

    #include<cstdio>
    #include<map>
    #include<vector>
    #include<stack>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<cstdlib> 
    #include<climits>
    #define PI acos(-1.0)
    #define INF 0x3fffffff
    using namespace std;
    typedef __int64 ll;
    typedef    __int64 LL;
    typedef __int64 int64;
    const ll MOD=1e9+7;
    const int64 Mod=1e9+7;
    const ll p=1e9+7;
    const double eps=1e-9;
    const int N=1e3+10;
    const int MAXN=200000;
    typedef int rl; 
    inline void r(rl&num){
        num=0;rl f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
        num*=f;
    } 
    LL quick_mod(LL a, LL b)  
    {  
        LL ans = 1;  
        a %= p;  
        while(b)  
        {  
            if(b & 1)  
            {  
                ans = ans * a % p;  
                b--;  
            }  
            b >>= 1;  
            a = a * a % p;  
        }  
        return ans;  
    }  
      
    LL C(LL n, LL m)  
    {  
        if(m > n) return 0;  
        LL ans = 1;  
        for(int i=1; i<=m; i++)  
        {  
            LL a = (n + i - m) % p;  
            LL b = i % p;  
            ans = ans * (a * quick_mod(b, p-2) % p) % p;  
        }  
        return ans;  
    }  
      
    LL Lucas(LL n, LL m)  
    {  
        if(m == 0) return 1;  
        return C(n % p, m % p) * Lucas(n / p, m / p) % p;  
    }  
    char ch[1010];
    int a[27];
    int main(){
        int T;
        r(T);
        while(T--){
            scanf("%s",ch);
            int len=strlen(ch);
            for(int i=0;i<len;i++)
            {
                 a[ch[i]-'a']++;
            }
            int sum=0,s=0;
            for(int i=0;i<26;i++)
            {
                if(a[i]&1){
                    a[i]--;
                    sum++;
                }
                if(a[i]){
                    s++;
                }
            }
            if(sum>1){
                printf("0
    ");
            }
            else{
                if(s==0||s==1){
                    printf("1
    ");
                }
                else{
                    len=(len-sum)/2;
                    int64 x=1;
                    for(int i=0;i<26&&s>1;i++)
                    {
                        if(a[i]){
                            s--;
                            x*=Lucas(len,a[i]/2);
                            len-=a[i]/2;
                            x%=Mod;
                        } 
                    }
                    printf("%I64d
    ",x);
                }
            }
            memset(a,0,sizeof(a));
        }
        return 0;
    }
    lucas AC代码

    换个思路问题 可以用 N!/a[0]!/..../a[25]! 乘逆元计算

  • 相关阅读:
    算法笔记--中国剩余定理
    算法笔记--辛普森积分公式
    算法笔记--数学之不定方程解的个数
    算法笔记--卢卡斯定理
    洛谷 P3808 【模板】AC自动机(简单版)洛谷 P3796 【模板】AC自动机(加强版)
    hihocoder #1419 : 后缀数组四·重复旋律4
    codevs 3044 矩形面积求并 || hdu 1542
    Stamps ans Envelope Sive UVA
    洛谷 P2061 [USACO07OPEN]城市的地平线City Horizon
    bzoj 3277: 串
  • 原文地址:https://www.cnblogs.com/Geek-xiyang/p/5334841.html
Copyright © 2011-2022 走看看