zoukankan      html  css  js  c++  java
  • 组合数(阶乘数质因子分解)

    C(n,m)   表示组合数,n>=m>=0

    以下适用范围:

    n<=1e6(or 1e7...)

    爆龙龙的答案需取模,允许取合数模

    时间复杂度 线性筛略大一点点 大概还是nlon(n)

    C(n,m)=n!/(m!*(n-m)!)

    举例说明一下为什么可以通过下面代码去计算阶乘数的所有质因子各自的数目。

    void factor_jc(int n)//分解n!的素数因子并记录个数 
    {
        //fac[i]=(prim[i]这个素数因子有几个)
        int i,up=n;for(i=1;i<=pri[0]&&pri[i]<=up;i++)
        {
            int tmp=n;
            while(tmp)
            {
                fac[i]+=tmp/pri[i];
                tmp/=pri[i];
            }
        }
        //fac[0]存素数最大到prim[]几; 
        fac[0]=max(fac[0],i);
    }

    比如求9!中质因子的个数:

    2的个数=9/2+9/22+9/23=4+2+1=7

    因为

      包含因子  2:2  4  6  8:fac[2]+=4(此时4和8仅记录第一个因子2)

      包含因子22:    4      8:fac[2]+=2 (此时4和8记录了第二个因子2)

      包含因子23:            8:fac[2]+=1 (此时8记录第三个因子2)

    所以因子2的个数等于4+2+1=7;

    同理:

    因为

      包含因子  3:3  6  9:fac[3]+=3(此时9仅记录第一个因子3)

      包含因子22:        9:fac[3]+=1 (此时9记录了第二个因子3)

    所以因子3的个数等于9/3+9/32=3+1=4;

    所以对于n!包含质因子x个数:fac[x]=n/x+n/x2+……+n/xk  (直到n/xk=0结束)。

    所以对于9!:

    fac[2]=9/2+9/22+9/23=4+2+1=7;

    fac[3]=9/3+9/32=3+1=4;

    fac[5]=9/5=1;

    fac[7]=9/7=1;

    因为下一个素数是11>9,所以结束。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+50;
    const ll mod=1e9+7;
    int pri[maxn+5],fac[maxn+5];
    void prime()
    {
        //prime[0]记录素数个数 
        memset(pri,0,sizeof(pri));
        for(int i=2;i<=maxn;i++)
        {
            if(!pri[i]) pri[++pri[0]]=i;
            for(int j=1;j<=pri[0]&&pri[j]<=maxn/i;j++)
            {
                pri[pri[j]*i]=1;
                if(i%pri[j]==0) break;
            }
        }
    }
    void factor_jc(int n)//分解n!的素数因子并记录个数 
    {
        //fac[i]=(prim[i]这个素数因子有几个)
        int i,up=n;
        if(up<0)up=-up;
        for(i=1;i<=pri[0]&&pri[i]<=up;i++)
        {
            int tmp=n;
            while(tmp)
            {
                fac[i]+=tmp/pri[i];
                tmp/=pri[i];
            }
        }
        //fac[0]存素数最大到prim[]几; 
        fac[0]=max(fac[0],i);
    }
    ll kpow(ll a,ll b)
    {
        ll ans=1,base=a;
        while(b)
        {
            if(b&1) ans=ans*base%mod;
            base=base*base%mod;
            b>>=1;
        }
        return ans;
    }
    ll C(int n,int m)
    {
        memset(fac,0,sizeof(fac));
        factor_jc(n);
        factor_jc(-m);//负数代表减 减去因子 
        factor_jc(m-n);//
        ll ans=1;
        for(int i=1;i<fac[0];i++)
            if(fac[i])ans=ans*kpow(pri[i],fac[i])%mod;
        return ans;
    }
    int main()
    {
        int n,m;
        prime();
        while(~scanf("%d%d",&n,&m))
            printf("%lld
    ",C(n,m));
    }
  • 相关阅读:
    递归遍历多维数组(树数据结构)的超级简单方式,并且可以递归超过200层,摘自<<PHP精粹:编写高效PHP代码>>
    http协议传输二进制数据以及对输入流(php://input)和http请求的理解
    一个非常简单的RPC服务
    php://input 打开的数据流只能读取一次,即读取一次之后读取的值为空
    soap的简单实现(PHP)
    使用PHP的curl扩展实现跨域post请求,以及file_get_contents()百度短网址例子
    jquery选取iframe
    算法之棋盘覆盖
    词法分析之实验报告
    简单的词法分析小程序
  • 原文地址:https://www.cnblogs.com/kkkek/p/11450696.html
Copyright © 2011-2022 走看看