一、基础概念(略)

质数

约数

同余

二、质数

A.质数筛法

暴力筛(略)

埃筛(\(O(nloglogn)\)

inline void prim(int limit) {//埃筛 
    vis[1] = 1;
    for (int i = 2;i <= limit; ++i) {
        if (!vis[i]) {
            prims[++p_cnt] = i;
            for (int j = i * i;j <= limit; j += i) vis[j] = 1;
        }
    }
}

欧筛(\(O(n)\)

inline void ola_prim(int limit) {//欧筛 
    vis[1] = 1;
    for (int i = 2;i <= limit; ++i) {
        if (!vis[i]) {
            vis[i] = i;
            prims[++p_cnt] = i;
        }           
        for (int j = 1;j <= p_cnt; ++j) {
            if (prims[j] > vis[i] || prims[j] > limit / i) break;
            vis[i * prims[j]] = prims[j];
        }
    }
} 

三、约数与同余

A.欧几里得算法

\[ gcd(a,b)=gcd(b,a\%b) \]
数学归纳法可推广到一般。

B.裴蜀定理

描述
如果任意整数\(a\)\(b\)不都为\(0\),则\(gcd(a,b)\)\(a\)\(b\)的线性组合集\(\{ax+by:x,y\in Z\}\)中的最小正元素。

证明
\(s\)是线性组合集\(\{ax+by:x,y\in Z\}\)中的最小正元素,\(q=\lfloor a/s\rfloor\)
所以必存在一组\(x,y\)使得\(ax+by=s\)

所以\(a\%s=a-qs=a-q(ax+by)=a(1-qx)+b(-qy)\)
因此\(a\%s\)也是\(a\)\(b\)的一个线性组合。

由于\(s\)是这个线性组合中最小正数,所以\(a\%s=0\)。即\(s|a\),同理,\(s|b\),所以\(gcd(a,b)\ge s\)

因为\(gcd(a,b)|s\)\(s>0\),所以\(gcd(a,b)\le s\)
\(gcd(a,b)=s\)
得证。

C.扩展欧几里得算法

四、组合计数

A.加法和乘法原理

加法原理:做一件事情,完成它有\(n\)类方式,第一类方式有\(m_1\)种方法,第二类方式有\(m_2\)种方法,…,第\(n\)类方式有\(m_n\)种方法,那么完成这件事情共有\(m_1+m_2+……+m_n\)种方法。

乘法原理:做一件事,完成它需要分成\(n\)个步骤,做第一步有\(m_1\)种不同的方法,做第二步有\(m_2\)种不同的方法,……,做第\(n\)步有\(m_n\)种不同的方法。那么完成这件事共有 \(m_1×m_2×m_3×…×m_n\)种不同的方法。

B.排列组合公式

全排列:\(A_n^m=\frac{n!}{(n-m)!}=A_{n-1}^{m}+A_{n-1}^{m-1}*m\)

组合数:\(C_n^m=\frac{n!}{m!(n-m)!}=C_{n-1}^{m-1}+C_{n-1}^m\)

性质:

  • \(\sum_{i=0}^nC_n^i=2^n\)(根据意义去思考)
  • \(\sum_{k=0}^n(-1)^kC_n^k=0\)
  • \(C_n^m=C_n^{n-m}\)
  • \(C_{n+m}^r=\sum_{i=0}^rC_n^iC_m^{r-i}\)

C.二项式定理

\[ (x+y)^n=C_n^0x^ny^0+C_n^1x^{n-1}y^1+...+C_n^{n-1}x^1y^{n-1}+C_n^nx^0y^n \]

可用数学归纳法证明。

D.容斥原理

交集相加减得并集。

E.斯特林数

  • 第一类斯特林数:\(n\)个不同元素构成\(m\)个圆排列的数目。
    \(s_1(n,m)=s_1(n-1,m-1)+s_1(n-1,m)*(n-1)\)
  • 第二类斯特林数:\(n\)个不同的元素拆分成\(m\)个集合的方案数。
    \(s_2(n,m)=s_2(n-1,m-1)+s_2(n-1,m)*m\)
  • 贝尔数:集合划分的方案数。
    \(B_n=\sum_{i=1}^ns_2(n,i)=\sum_{k=0}^nC_n^kB_k\)

F.康托展开

\[ ans=1+\sum_{i=1}^nA[i]*(n-i)! \]
\(A[i]\):当前位置往后比当前位置数小的个数,可用树状数组求。

补充

进制转换(略)

球盒问题

\(a\)个球,\(b\)个盒,求满足放置条件的方案数。

编号 球相同 盒相同 盒可为空 计算
\(1\) × × \(s_2(a,b)\)
\(2\) × \(\sum_{i=1}^{b}s_2(a,i)\)
\(3\) × × × \(b!s_2(a,b)\)
\(4\) × × \(b^a\)
\(5\) × \(dp[n][m]\)
\(6\) \(dp[n+m][m]\)
\(7\) × × \(C_{a-1}^{b-1}\)
\(8\) × \(C_{a+b-1}^{b-1}\)

说明:

表中\(s_2\)指的是第二斯特林数。

递推式:\(s_2(n,m)=s_2(n-1,m-1)+s_2(n-1,m)*m\)

同时,贝尔数\(Bell_n=\sum_{i=1}^{b}s_2(a,i)\)

情况\(5\)\(6\)的递推式:\(dp[n][m]= dp[n-m][m]+ dp[n-1][m-1]\)

简要分析如下:

  1. \(n\)个不同的元素拆分成\(m\)个集合的方案数,等同于第二斯特林数。
  2. 允许出现空集,所以\(\sum\)求和。
  3. 容斥原理做,或者可以理解为因为盒子不同,所以直接乘上盒子的排列。
  4. 最好理解:每个球有\(b\)种放法。
  5. 这个问题等效成把一个数n拆成m个数,且先拆出的数不小于后拆出的数(避免重复情况)。如果这么拆:\(x_1+x_2+x_3+...+x_m=n (x_i>=1)\)。当\(x_1=1\)时,后面的拆法表示成\(dp[n-1,m-1]\)。当\(x_1>=2\)时,式子可以变成\((x_1-1)+(x_2-1)+...+(x_m-1)=n-m\)。所以后面的拆法表示成\(dp[n-m,m]\)。所以得到递推式。
  6. 在情况\(5\)下,每盒先放一个。
  7. 插板问题。
  8. 同插板问题。
优质内容筛选与推荐>>
1、*#【Python】【基础知识】【模块】【tkinter】【学用tkinter画图/制作窗口】
2、bootstrap模态框手动开启关闭与设置点击外部不关闭
3、保存Bitmap图像
4、background-clip与background-origin两者的区别
5、Python学习笔记模式匹配与正则表达式之使用和不使用正则表达式


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号