• 0x36 组合计数


    组合计算的性质:

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

    C(n,m)=C(m-n,m); C(n,m)=C(n,m-1)+C(n-1,m-1);

    二项式定理:(a+b)^n=sigema(k=0~n) C(k,n)*a^k*b^(n-k)

    lucas定理:C(n,m)≡C(n%p,m%p)*C(n/p,m/p)  (mod p)

    catalan数: Cat(n)=C(n,2n)/n+1  Cat(n)=Cat(n-1)*(4n-2)/(n+1)

    计算系数 通过二项式定理变形其实就是求C(n,k)*a^n*b^m,用下逆元

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=10007;
    
    LL quick_pow(LL A,LL p)
    {
        int ret=1;
        while(p!=0)
        {
            if(p%2==1)ret=(ret*A)%mod;
            A=(A*A)%mod;p/=2;
        }
        return ret;
    }
    LL jiecheng(LL k)
    {
        LL ret=1;
        for(int i=1;i<=k;i++)ret=(ret*i)%mod;
        return ret;
    }
    LL getniyuan(LL k)
    {
        return quick_pow(k,mod-2);
    }
    
    int main()
    {
        LL a,b,k,n,m;
        scanf("%lld%lld%lld%lld%lld",&a,&b,&k,&n,&m);
        LL ans=( (jiecheng(k)*getniyuan( jiecheng(n)*jiecheng(k-n)%mod )%mod) *
                  (quick_pow(a,n)*quick_pow(b,m)%mod) )%mod;
        printf("%lld
    ",ans);
        return 0;
    }
    计算系数

    Counting Swaps 神仙题,%lyd吧。。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+9;
    
    LL quick_pow(LL A,LL p)
    {
        int ret=1;
        while(p!=0)
        {
            if(p%2==1)ret=(ret*A)%mod;
            A=(A*A)%mod;p/=2;
        }
        return ret;
    }
    LL jiecheng(LL k)
    {
        LL ret=1;
        for(int i=1;i<=k;i++)ret=(ret*i)%mod;
        return ret;
    }
    LL getniyuan(LL k)
    {
        return quick_pow(k,mod-2);
    }
    
    int nxt[110000];
    bool v[110000];
    LL dfs(int x,int d)
    {
        if(v[x]==true)return d;
        v[x]=true;
        dfs(nxt[x],d+1);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n;
            scanf("%d",&n);
            for(int i=1;i<=n;i++)scanf("%d",&nxt[i]);
            
            LL tot=0,ans=1,cnt;cnt=n;
            memset(v,false,sizeof(v));
            for(int i=1;i<=n;i++)
            {
                if(v[i]==false)
                {
                    int L=dfs(i,0);
                    if(L>1)
                    {
                        tot++;
                        ans=(ans*quick_pow(L,L-2)%mod)*getniyuan(jiecheng(L-1))%mod;
                    }
                    else cnt--;
                }
            }
            if(tot==0)printf("1
    ");
            else
            {
                ans=ans*jiecheng(cnt-tot)%mod;
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    Count Swaps

    bzoj1951 由欧拉定理的推论,变成计算sigema(d|n)C(d,n)%(mod-1),这个用卢卡斯定理搞,但是mod不是质数,那么分解分别搞,然后得到4个同余方程,解出就是指数了,最后快速幂即可。

    upd:感觉之前的阶乘模数有点假。。但是应该是对的

    快速幂+crt并没有exgcd优秀的说。。。卡了一波常数才过的。。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=999911659;
    const LL md[]={2,3,4679,35617};
    
    int quick_pow(int A,int p,int mod)
    {
        int ret=1;
        while(p!=0)
        {
            if(p%2==1)ret=(LL)ret*A%mod;
            A=(LL)A*A%mod;p/=2;
        }
        return ret;
    }
    LL fac[4][41000],fac_inv[4][41000];
    void initC()
    {
        for(int j=0;j<=3;j++)fac[j][0]=1,fac_inv[j][0]=1;
        for(int i=1;i<=md[3];i++)
            for(int j=0;j<=3;j++)
                fac[j][i]=fac[j][i-1]*i%md[j],fac_inv[j][i]=quick_pow(fac[j][i],md[j]-2,md[j]);
    }
    LL getC(LL n,LL m,LL p){return fac[p][n]*fac_inv[p][m]%md[p]*fac_inv[p][n-m]%md[p];}
    LL lucas(LL n,LL m,LL p)
    {
        LL ans=1;
        while(m>0)
        {
            LL a=n%md[p],b=m%md[p];
            if(a<b)return 0;
            ans=ans*getC(a,b,p)%md[p];
            n/=md[p],m/=md[p];
        }
        return ans;
    }
    
    LL a[4];
    LL solve(LL n,LL k)
    {
        for(int i=0;i<=3;i++)a[i]=lucas(n,k,i);
        LL M=mod-1,x=0;
        for(int i=0;i<=3;i++)//crt
            x=(x+a[i]*(M/md[i])*quick_pow(M/md[i],md[i]-2,md[i]))%(mod-1);
        return x;
    }
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        initC();
        int n,G,p=0;
        scanf("%d%d",&n,&G);
        if(G==mod){printf("0
    ");return 0;}
        for(int i=1;i*i<=n;i++)
            if(n%i==0)
            {
                p=(p+solve(n,i))%(mod-1);
                if(i*i!=n)p=(p+solve(n,n/i))%(mod-1);
            }
        printf("%d
    ",quick_pow(G,p,mod));
        return 0;
    }
    bzoj1951(upd)
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=999911659;
    const LL md[4]={2,3,4679,35617};
    
    LL exgcd(LL a,LL b,LL &x,LL &y)
    {
        if(a==0)
        {
            x=0;y=1;
            return b;
        }
        else
        {
            LL tx,ty;
            LL d=exgcd(b%a,a,tx,ty);
            x=ty-b/a*tx;
            y=tx;
            return d;
        }
    }
    LL quick_pow(LL A,LL p)
    {
        LL ret=1;
        while(p!=0)
        {
            if(p%2==1)ret=(ret*A)%mod;
            A=(A*A)%mod;p/=2;
        }
        return ret;
    }
    LL inv(LL a,LL p)
    {
        LL x,y;
        LL d=exgcd(a,p,x,y);
        return (x%p+p)%p;
    }
    
    //---------------------------------------------------
    
    LL jc[110000];
    LL lucas(LL N,LL M,LL p)
    {
        LL ans=1;
        while(M>0)
        {
            LL a=N%p,b=M%p;
            if(a>b)return 0;
            
            ans=ans*jc[b]%p;
            ans=ans*inv(jc[a],p)%p;
            ans=ans*inv(jc[b-a],p)%p;
            
            N/=p;M/=p;
        }
        return ans;
    }//lucas
    LL g[110000];
    void getzs(LL n)
    {
        jc[0]=1;
        for(int i=1;i<=md[3];i++)jc[i]=(jc[i-1]*i)%(mod-1);
        
        for(int i=1;i*i<=n;i++)
        {
            if(n%i==0)
            {
                for(int j=0;j<=3;j++)
                    g[j]=(g[j]+lucas(i,n,md[j]))%md[j];
                if(i!=n/i)
                {
                    for(int j=0;j<=3;j++)
                        g[j]=(g[j]+lucas(n/i,n,md[j]))%md[j];
                }
            }
        }
    }
    
    //---------------------------------------------------
    
    LL u1,v1,u2,v2;
    void merge()
    {
        LL A=u1,B=u2,K=v2-v1,x,y;
        LL d=exgcd(A,B,x,y);
        
        x=(x*(K/d)%(B/d)+(B/d))%(B/d);
        v1=u1*x+v1;
        u1=u1/d*u2;
    }
    LL solve()
    {
        u1=md[0],v1=g[0];
        for(int i=1;i<=3;i++)
            u2=md[i], v2=g[i], merge();
        return v1;
    }
    
    int main()
    {
        LL n,g;
        scanf("%lld%lld",&n,&g);g%=mod;
        if(g==0){printf("0
    ");return 0;}
        
        getzs(n);
        LL p=solve();
        printf("%lld
    ",quick_pow(g,p));
        return 0;
    }
    bzoj1951
  • 相关阅读:
    GAMBIT、ICEM、HYPERMESH耦合面的处理方法
    如何用hypermesh生成包含interface的流体网格
    python求数字位数的方法
    drawPython
    Python入门计划
    书法与篆刻创作结课
    易忽视的Python知识点
    Ubuntu中,wxpython的TextCtrl引发的error:_pixman_log_error
    在Ubuntu15.10中,使用wxPython的webview和JS进行交互
    PyCharm导入tensorflow包
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9401743.html
Copyright © 2020-2023  润新知