组合数相关问题

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\n");
        }
        else{
            if(s==0||s==1){
                printf("1\n");
            }
            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\n",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\n");
        }
        else{
            if(s==0||s==1){
                printf("1\n");
            }
            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\n",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\n");
        }
        else{
            if(s==0||s==1){
                printf("1\n");
            }
            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\n",x);
            }
        }
        memset(a,0,sizeof(a));
    }
    return 0;
}
lucas AC代码

 

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

 

posted @ 2016-03-29 21:25  zxMrlc  阅读(195)  评论(0编辑  收藏  举报