ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

紫书学习 10.数学概念与方法--计数问题基础

2022-07-20 21:31:12  阅读:178  来源: 互联网

标签:10 phi 紫书 -- sum cap 个数 表达式 欧拉


基本计数原理

加法原理:做一件事情有n种办法,每种办法有pi种方案。

乘法原理:做一件事有n个步骤,每个步骤有pi种方案。

容斥原理:要计算一些互不独立的集合的并集,需要用到容斥原理。

比如求三个集合并的元素个数:

\[|A\cup B \cup C|=|A|+|B|+|C|-|A\cap B|-|A\cap C|-|B\cap C|+|A\cap B \cap C| \]

左边是并,右边是交。右边,奇数时项为加号,偶数时的项为减号。

排列组合

有重复元素的全排列

假设有n种元素,每种元素可以选择\(p_i\)个,求全排列数。

可以采用消序法。假设\(\sum p_i=s\)

\[ans=A_s^s/(\prod A_{p_i}^{p_i}) \]

可以重复选择的组合

假设有n种不同的元素,每种元素可以多次选择,最后选择k个元素,问有多少种方案。

假设每种元素选择\(p_i\)个,则根据问题列出表达式:

\[\sum p_i=k \]

设表达式的一个解为\((p_1,p_2,...p_n)\),原问题即转化为求其非负整数解的个数。

等式两边同时+n,令\(p_i+1=y_i\),则原式转化为:

\[\sum y_i=n+k \]

求该表达式的正整数解的个数。

这是经典的插板法的应用,相当于有\(n-k\)个1,要在\(n+k-1\)个空隙中选n-1 个位置插板:\(ans=C_{n+k-1}^{n-1}\)

二项式系数的横向递推

根据二项式系数的表达式,容易得出:

\[C_n^i=C_n^{i-1}*(n-i+1)/i \]

注意这种写法容易爆,而且不能把除法写到前面,因为不一定除得尽。

但是可以用这种方法递推出每个系数的唯一分解式,这是不会爆的。

约数个数

根据唯一分解表达式:

\[n=\prod p_i^{a_i} \]

在根据乘法原理可得:

\[num=\prod(a_i+1) \]

因此只需要对一个数做唯一分解,就可以求出它的约数个数。

欧拉函数

欧拉函数phi[i]表示1~i中与i互素的数的个数。

容斥原理与欧拉函数

应用容斥原理。

1~n中总数为n。

首先从n中减去质因子\(p_i\)倍数的个数,即\(-\sum n/p_i\)

然后再加上同时是两个质因子倍数的个数,即\(+\sum n/(p_ip_j)\)

再减去是三个质因子倍数的个数

再加.......

这样计算的时间代价很高,有时甚至不如暴力枚举。

更简洁的等价表达式

\[\phi(i)=n*\prod(1- \frac{1}{p_i}) \]

因此只需要一次质因数分解,就可以算出一个数的欧拉函数。

埃筛求1~n的欧拉函数

紫书上说,时间复杂度是\(O(nloglogn)\),比暴力快一些。

void cal_phi(int k){
    phi[1]=1;
    for(int i=2;i<=k;i++){
        if(!phi[i]){
            for(int j=i;j<=k;j+=i){
                if(!phi[j])phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}

埃筛求法比较直观,看上去,素数的相邻倍数之间的数应该是和素数倍数互素的。

欧拉筛求1~n的欧拉函数

用空间换时间,时间复杂度是线性的。

欧拉筛求欧拉函数的原理和表达式关系非常接近。

可以通过phi[i]推出phi[primes[j]*i]的值:

\[phi(p_j*i)= \begin{cases} (p_j-1)*phi(i),\quad 当primes(j)不是i的最小质因子\\ p_j*phi(i), \quad 当primes(j)是i的最小质因子 \end{cases} \]

刚好欧拉筛就是用最小质因子来筛素数的,可以顺便求欧拉函数。

void cal_phi(int k){
    phi[1]=1;
    for(int i=2;i<=k;i++){
        if(!st[i]){
           phi[i]=i-1;//如果是素数,答案就是i-1
           primes[++cnt]=i;
       	}
        for(int j=1;primes[j]<=k/i;j++){
            st[primes[j]*i]=1;
            if(i%primes[j]){//pj不是最小质因子
                phi[primes[j]*i]=phi[i]*(primes[j]-1)
            }
            else{//pj是i的最小质因子
                phi[primes[j]*i]=phi[i]*primes[j];
                break;
            }
        }
    }
}

标签:10,phi,紫书,--,sum,cap,个数,表达式,欧拉
来源: https://www.cnblogs.com/tshaaa/p/16499912.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有