zoukankan      html  css  js  c++  java
  • 数论基础知识(2)【转】

    声明

    截取oy同学的博客:https://www.luogu.org/blog/ollie906086458/post-1-post
    之后再自己整理

    六、CRT/EXCRT

    1.CRT

    转载某大佬(%%%),蒟蒻修改部分

    1.定义:

    若m[1],m[2],...,m[n] 是两两互质的正整数, (M= prod_{i=1}^n{m[i]})(M[i]=M/m[i] ,t[i]) 是线性同余方程 (M[i] * t[i] ≡1(mod m[i]))的一个解。对于任意的(n)个整数(a[1], a[2], a[3], ... , a[n]),则同余方程组为:

    [left{egin{matrix} xequiv a_{1}pmod{m_{1}}\ xequiv a_{2}pmod{m_{2}}\ ......\ xequiv a_{n}pmod{m_{n}} end{matrix} ight. ]

    有整数解,方程组的解为

    [x=a_{1}M_{1}t_{1}+a_{2}M_{2}t_{2}+...+a_{n}M_{n}t_{n} ]

    并且在%M意义下有唯一解。

    2.证明:

    因为(M[i] = M/m[i]) 是除(m[i]) 之外所有模数的倍数,所以 (∀) (任意)(k eq i)(a[i]M[i]t[i]≡0(mod m[k])).又因为 (a[i]M[i]t[i] ≡a[i] (mod m[i])),所以代入(x)

    [x=sum_{i=1}^{n}a_{i}M_{i}t_{i} ]

    3.结论:

    中国剩余定理给出了模数两两互质的线性同余方程组的一个特殊解。方程组的通解可以表示为(x+kM(k∈Z))。有些题目要求我们求出最小的非负整数解,只需把x对M取模,并让x落在0~M-1的范围内即可。

    int intchina(int r)
    {
        int Mi,x,y,d,ans=0;
        int M=1;//注意取1
        for(int i=1;i<=r;i++) M*=m[i];
        for(int i=1;i<=r;i++){
            Mi=M/m[i];
            exgcd(Mi,m[i],d,x,y);
            ans=(ans+Mi*x*a[i])%M; //Mi相当于Mi,x—>ti
        }
        return (ans+M)%M;//防负数
    }
    
    

    P1495 曹冲养猪

    2.EXCRT

    某位神仙说提高不会考,如果考到我认命,如果实在想学可以点击这里

    七、线性代数

    0.前置

    线性代数比较难(矩阵)而且不咋考,所以就马马虎虎地走个过场

    1.快速幂

    这个大家都会,我就只贴板子了

    如果你实在要搞懂原理 戳我

    求:

    [a^{b}\,mod\,p ]

    code:

    ll quick_pow(ll a, ll b, ll p)//a^b mod p
    {
    	ll t=1;
    	while(b)
    	{
    		if(b&1) t=t*a%p;
    		a=a*a%p;
    		b>>=1;
    	}
    	return t;
    }
    
    

    2.矩阵相关

    %%%大佬 可爱即是正义

    直接使用传送术(懒得排了,也不是很重要的东西)

    可爱即是正义 的博客

    3.*高斯消元

    某位神级清华sang师说高斯消元noip不会考,不属于提高组,所以不讲,如果感兴趣自己下去查吧。

    八、组合数学

    前置:这个也是考的比较多的

    1.卡特兰数(卡姿兰数)

    说明:原博客

    1.卡特兰数是啥:

    卡特兰数是一种经典的组合数,经常出现在各种计算中,其前几项为 : 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, ...

    TIP:Cn,hn,fn均表示卡特兰数(在这)

    2.卡特兰数的公式

    ① 递归公式1

    [f(n)=sum_{i=0}^{n-1}f(i)*f(n-i-1) ]

    如果我们用这个公式显然我们要使用递归算法,那么数据一大就在时空上很麻烦

    ② 递归公式2

    [f(n)=frac{f(n-1)*(4*n-2)}{(n+1)} ]

    这个公式应用递推,看上起十分和善

    但对大数据呢?

    我们注意到大数据的时候 f(n) 会很大,这时候题目一般会让你对某素数取模(当然你可以打高精度

    但你在取模过程中难保一个 f(n)%mod=0

    那么根据公式下面所有的数都会等于0,于是你就愉快的WA了

    ③ 组合公式1

    [f(n)=frac{C_{2n}^{n}}{(n+1)} ]

    卡特兰数可以与组合数联系起来,得到上面的公式

    而组合数就是一个杨辉三角,可以递推得到

    但我们发现对于大数据你要取模,而对于除法你是没办法用膜的性质的(当然你可以应用逆元),所以造成了麻烦

    ④ 组合公式2

    [f(n)=C_{2n}^{n}-C_{2n}^{n-1} ]

    与组合数公式1不同这个是两个组合数的减法

    减法是可以用膜的性质的,于是你可以愉快的AC了。

    3.卡特兰数的应用

    ①、进出栈问题:

    栈是一种先进后出(FILO,First In Last Out)的数据结构.如下图1,2,3,4顺序进栈,那么一种可能的进出栈顺序是:1In→2In→2Out→3In→4In→4Out→3Out→1Out, 于是出栈序列为1,3,4,2。

    那么一个足够大的栈的进栈序列为1,2,3,⋯,n时有多少个不同的出栈序列?

    例题

    我们可以这样想,假设 x 是最后一个出栈的数。

    由于x是最后一个出栈的,所以可以将已经出栈的数分成两部分

    1.比 x 小

    2.比 x 大

    比x小的数有x-1个,所以这些数的全部出栈方案数为f[x-1]

    比x大的数有n-x个,所以这些数的全部出栈方案数为f[n-x]

    所以一共有 (f[x-1]*f[n-x]) 种方案。显而易见,(x) 取不同值时,产生的出栈序列是相互独立的,所以结果可以累加。(x)的取值范围为 (1) 至 $ n$,所以结果就为

    (f[n] = f[0] * f[n-1] + f[1] * f[n-2] + ... + f[n-1] * f[0])

    ②. 二叉树构成问题

    有n个结点,问总共能构成几种不同的二叉树?

    (1)先考虑只有一个节点的情形,设此时的形态有 (f[1]) 种,那么很明显 (f[1]=1)

    (2)如果有两个节点呢?我们很自然想到,应该在 (f[1]) 的基础上考虑递推关系。 那么,如果固定一个节点后,左右子树的分布情况为(1=1+0=0+1),故有(f[2] = f[1] + f[1])

    (3)如果有三个节点,我们需要考虑固定两个节点的情况么?(当然不,因为当节点数量大于等于(2)时,无论你如何固定,其形态必然有多种 我们考虑固定一个节点,即根节点)。好的,按照这个思路,还剩2个节点,那么左右子树的分布情况为(2=2+0=1+1=0+2)。 所以有(3)个节点时,递归形式为 (f[3]=f[2]+f[1]*f[1]+f[2])。(注意这里的乘法,因为左右子树一起组成整棵树,根据排列组合里面的乘法原理即可得出)

    (4)那么有n个节点呢?我们固定一个节点,那么左右子树的分布情况为
    (n-1=n-1 + 0 = n-2 + 1 = … = 1 + n-2 = 0 + n-1)。此时递归表达式为(f[n] = f[n-1] + f[n-2]f[1] + f[n-3]f[2] + … + f[1]f[n-2] + f[n-1])

    即给定(N)个结点,能构成(h(N))种不同的二叉树。(h(N))为卡特兰数的第(N)项。(二叉树性质)

    ③、凸多边形的三角形划分

    一个凸的(n)边形,用直线连接他的两个顶点使之分成多个三角形,每条直线不能相交,问一共有多少种划分方案。

    这也是非常经典的一道题。我们可以这样来看,选择一个基边,显然这是多边形划分完之后某个三角形的一条边。图中我们假设基边是(p1-pn),我们就可以用(p1,pn)和另外一个点假设为(pi)做一个三角形,并将多边形分成三部分,除了中间的三角形之外,一边是(i)边形,另一边是(n-i+1)边形。(i)的取值范围是(2)(n-1)。所以本题的解(c(n)=c(2)c(n-1)+c(3)c(n-2)+...c(n-1)c(2))。令(t(i)=c(i+2))。则(t(i)=t(0)t(i-1)+t(1)t(i-2)...+t(i-1)t(0))。很明显,这就是一个卡特兰数了。

    ④、求n+1个叶子的满二叉树的个数

    QQ20151105-6

    不证,知道就行

    ⑤、路径问题

    在n*n的格子中,只在下三角行走,每次横或竖走一格,有多少中走法?

    其实向右走相当于进栈,向左走相当于出栈,本质就是n个数出栈次序的问题,所以答案就是卡特兰数。(利用这个模型,我们解决这个卡特兰问题的变形问题,并顺便给进出栈问题的解法一个几何解释)

    神奇的卡特兰数

    ⑥、划分问题

    将一个凸n+2边形区域分成三角形区域的方法数?

    神奇的卡特兰数

    证明都差不多啦,自己研究去吧

    ⑦、握手问题

    2n 个人均匀坐在一个圆桌边上,某个时刻所有人同时与另一个人握手,要求手之间不能交叉,求共有多少种握手方法

    4、引理

    这就不说了,没啥对考试太实用的,如果实在想看就往上翻,去原博客看,考试知道这些就行了

    5、code

    说了一堆终于到终点了哈

    代码来自 xiejinhao (%%%)

    ①公式1:
    #include<cstdio>
    #define MAX_N 20//这你自己看要定义多大吧
    #define ll long long
    using namespace std;
    int n;
    ll f[MAX_N];
    int main()
    {
        f[0]=f[1]=1;
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<i;j++)
            {
                f[i]+=f[j]*f[i-j-1];
            }
        }
        printf("%lld",f[n]);
        return 0;
    }
    
    
    
    ②公式2:
    #include<cstdio>
    #define MAX_N 20
    #define ll long long
    using namespace std;
    int n;
    ll f[MAX_N];
    int main()
    {
        f[0]=f[1]=1;
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            f[i]+=f[i-1]*(4*i-2)/(i+1);
        }
        printf("%lld",f[n]);
        return 0;
    }
    
    
    
    ③公式3:
    #include<cstdio>
    #define MAX_N 20
    #define ll long long
    using namespace std;
    int n;
    ll c[MAX_N*2][MAX_N];
    int main(){
    
        scanf("%d",&n);
        for(int i=1;i<=2*n;i++)
        {
            c[i][0]=c[i][i]=1;
            for(int j=1;j<i;j++)
            {
                c[i][j]=c[i-1][j]+c[i-1][j-1];
            }
        }
        printf("%lld",c[2*n][n]/(n+1));
        return 0;
    }
    
    
    
    ④公式4:
    #include<cstdio>
    #define MAX_N 20
    #define ll long long
    using namespace std;
    int n;
    ll c[MAX_N*2][MAX_N];
    int main(){
    
        scanf("%d",&n);
        for(int i=1;i<=2*n;i++)
        {
            c[i][0]=c[i][i]=1;
            for(int j=1;j<i;j++)
            {
                c[i][j]=c[i-1][j]+c[i-1][j-1];
            }
        }
        printf("%lld",c[2*n][n]-c[2*n][n-1]);
        return 0;
    }
    
    
    

    不懂看公式去

    卡姿兰数完结

    2、排列组合

    1、计数原理:

    如果 A 地到 B 地有三条路径,B 地到 C 地有两条路径,那么A 到 C 共有 2 * 3 = 6 种方案
    如果 A 还有一种直接到 C 的方案,那么就一共有 7 种方案

    上面就是加法原理和乘法原理(不知道自行百度好像不知道也无所谓哦

    2、排列和组合:

    从 n 个元素中取出 m 个元素,排成一排,叫做从 n 个元素中取出 m 个元素的一个排列

    [A_{n}^{m}=frac{n!}{(n-m)!} ]

    从 n 个元素中取出 m 个元素的所有组合(不管其顺序)的个数,叫做 n 个元素中取出 m 个元素的组合数

    [C_{n}^{m}=frac{n!}{m!(n-m)!} ]

    这东西太多了,我们讲几个基础的

    [C_{n}^{m}=C_{n}^{n-m},C_{n}^{0}=C_{n}^{n}=1 ]

    可以理解为:将原本的每个组合都反转,把原来没选的选上,原来选了的去掉,这样就变成从n个元素种取出n−m个元素,显然方案数是相等的。

    [C_{n}^{m}=C_{n-1}^{m}+C_{n-1}^{m-1} ]

    可理解为:含特定元素的组合有(C^{m-1}_{n-1}),不含特定元素的排列为(C^{m}_{n-1})

    组合数求和公式:

    [C_{n}^{0}+C_{n}^{1}+C_{n}^{2}+...+C_{n}^{n}=2^{n} ]

    自己记去

    3、二项式定理

    可以将x+y的任意次幂展开成和的形式

    [(x+y)^{n}=inom{n}{0}x^{n}y^{0}+inom{n}{1}x^{n-1}y^{1}+inom{n}{2}x^{n-2}y^{2}+...+inom{n}{n-1}x^{1}y^{n-1}+inom{n}{n}x^{0}y^{n} ]

    其中每个(inom{n}{k})为一个称作二项式系数的特定正整数,其等于(frac{n!}{k!(n-k)!})。这个公式也称二项式公式或二项恒等式。使用求和符号,可以把它写作

    [(x+y)^{n}=sum_{k=0}^{n}inom{n}{k}x^{n-k}y^{k}=sum_{k=0}^{n}inom{n}{k}x^{k}y^{n-k} ]

    P1313 计算系数

    4、杨辉三角

    来自古人的神秘力量

    大佬博客的搬运工——ollie

    杨辉三角可以帮助你更好地理解和记忆组合数的性质:

    1. (n)行的(m)个数可表示为 (C^{m-1}_{n-1}),即为从(n-1)个不同元素中取(m-1)个元素的组合数。
    2. (n)行的数字有(n)项。
    3. 每行数字左右对称(第(n)行的第(m)个数和第(n-m+1)个数相等,(C_{n}^{m}=C_{n}^{n-m}),由(1)开始逐渐变大。
    4. 每个数等于它上方两数之和(第(n+1)行的第(i)个数等于第(n)行的第(i-1)个数和第(i)个数之和,即(C_{n+1}^{i}=C^{i}_{n}+C_{n}^{i-1})
    5. ((a+b)^{n})的展开式中的各项系数依次对应杨辉三角的第(n+1)行中的每一项(二项式定理)。

    code:

    c[1][1] = 1;
    	for(int i = 2; i <= n; i++)
    	for(int j = 1; j <= i; j++)
    	{
    		c[i][j] = c[i-1][j] + c[i-1][j-1];
    	}
    
    

    P1118 数字三角形

    P2822 组合数问题

    九、数学期望

    所有的权值乘以它对应的概率

    通俗一点就是设(X[i])(i)的权值,(P[i])(i)对应出现的概率,期望值为(f),有:

    [f=sum_{i=1}^{n}X[i]* P[i] ]

    完结撒花

    还有部分内容未补上,后期补充上去

  • 相关阅读:
    Activity 与ListActivity的区别
    自定义标题栏
    解决小程序无法触发SESSION问题
    js数组与字符串经常用的几种简单的方法
    python程序与进制的执行过程
    常问的 web前端 问题
    如何判断页面滑到了屏幕最底部
    http请求状态保持的四种方法
    vue知识点归纳与总结(笔记)
    Nginx常用命令及使用场景
  • 原文地址:https://www.cnblogs.com/tyner/p/11847237.html
Copyright © 2011-2022 走看看