zoukankan      html  css  js  c++  java
  • 【数论】排列组合问题

    排列

    定义:

    从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)表示

    公式:

    A(n,m)=n(n-1)*(n-2)*……*(n-m+1)= n!/(n-m)!

    PS:此外规定0!=1

    特殊排列:

    • 不全相异元素的排列:

    在n个元素中 n1个元素彼此相同 有n2个元素彼此相同......有nm个元素彼此相同 并且n1+n2+...+nm=n

    其排列数公式为:n!/(n1!*n2!*...*nm!)

    【引例】把3个相同的黄球 2个相同的蓝球 4个相同的白球排成一排 有(3+2+4)!/(3!*2!*4!)=1260

    • 圆排列

    从n个数中取m个 不分首尾地排成一个圆圈的排列叫做圆排列 方案数为A(n,m)/m=n!/(m*(n-m)!)


    组合

    定义:

    从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示

    公式:

    C(n,m)=A(n,m)/m!=n!/(m!(n-m)!) 因为多出了一个全排列需要删去

    可重复组合:从n个元素中 取出r个元素组成一个组合 且允许这r个重复使用 记为H(n,r)=C(n+r-1,r)

    性质:

    1. C(n,m)=C(n,n-m) 规定:C(n,0)=C(n,n)=1
    2. C(n+1,m)=C(n,m)+C(n,m-1) 杨辉三角递推

    二项式定理:

    (a+b)nni=0C(n,i)a(n-i)bi

    二项式系数:C(n,i) 运用杨辉三角

    【例题】洛谷P1313 [NOIP2011TG]计算系数:https://www.luogu.org/problemnew/show/P1313

    题解链接:https://www.cnblogs.com/BrokenString/p/9665237.html


    Lucas定理

    定义:

    Lucas(n,m,p)=C(n%p,m%p)* Lucas(n/p,m/p,p)

    Lucas定理是用来求C(n,m) mod p的值,p是素数

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define LL long long
    LL T,n,m,p;
    LL quickpow(LL a,LL b)
    {
        LL ret=1;
        while(b)
        {
            if(b&1) ret=ret*a%p;
            a=a*a%p;
            b>>=1;
        }
        return ret;
    }
    LL C(LL n,LL m)
    {
        if(m>n) return 0;
        LL a=1,b=1;
        for(LL i=n-m+1;i<=n;i++)
        a=a*i%p;//计算n!/(n-m)! 
        for(LL i=2;i<=m;i++)
        b=b*i%p;//计算1/m! 
        return a*quickpow(b,p-2)%p;//费马小定理求逆元 
    }
    LL Lucas(LL n,LL m)
    {
        if(!m) return 1;
        else return (C(n%p,m%p)*Lucas(n/p,m/p))%p;//递推公式 
    }
    int main()
    {
        scanf("%lld",&T);
        while(T)
        {
            T--;
            scanf("%lld%lld%lld",&n,&m,&p);
            printf("%lld
    ",Lucas(n,m));
        }
    }
    View Code

    Catalan数列

    定义:

    给定n个0和n个1,它们按照某种顺序排成长度为2n的序列 满足任意前缀中0的个数都不少于1的个数的序列数量为:Catn=C(2n,n)/(n+1)

    有关题目:

    • n个左括号和n个右括号组成的合法括号序列数量为Catn
    • 1,2...n经过一个栈 形成合法的出栈顺序数量为Catn
    • n个节点构成的不同二叉树的数量为Catn
    • 在平面直角坐标系上 每步只能向上或者向右走 从(0,0)到(n,n)并且除两个端点外不接触直线y=x的路线数量为2Catn
    • 在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成了若干个三角形。任务是键盘上输入凸多边形的边数n,求不同划分的方案数f(n)
    • n层的阶梯切割为n个矩形的切法数

    这里给出一个较为详细的dalao的blog:https://blog.csdn.net/duanruibupt/article/details/6869431

    小技巧:

    如果看到

    n=1,answer=1;

    n=2,answer=2;

    n=3,answer=5;

    n=4,answer=14;

    n=5,answer=42;

    基本可以往卡特兰数方面想..

  • 相关阅读:
    Visual Studio 2019 开发 Python 及
    Delphi 的环境配置
    Delphi 的 TMS 控件安装方法
    网络爬虫-书籍与框架
    建筑行业(项目管理) BI 数据可视化分析案例
    DeepNude(一健脱衣)的算法以及通用图像生成的理论与实践研究
    matlab生成HEX文件-任意信号 大于64K长度
    SDRAM总结
    function [ binary,decimal ] = num2binary16( number )
    任意时钟分频
  • 原文地址:https://www.cnblogs.com/BrokenString/p/9664899.html
Copyright © 2011-2022 走看看