首页 > 其他分享 >组合基础

组合基础

时间:2024-02-15 11:23:05浏览次数:35  
标签:种颜色 所有 组合 cup cap 基础 times cdots

OI 中的组合,基本指组合计数。组合极值一般是贪心题或者 dp 题。

【组合数】

组合数 \(C^m_n=(^n_m)\)。

注意:求逆元前,请一定判断清楚,是否可能不存在逆元!!!

  1. \(C^m_n = C^m_{n-1}+C^{m-1}_{n-1}\)。

    c[n][m] = c[n - 1][m] + c[n - 1][m - 1];

    这个方法主要问题在于空间。

    优点:可以把 c[1 ~ n][1 ~ m] 全部求出来,好写。

    缺点:空间大。

    复杂度:\(O(nm)\)。

    适用情况:\(n,m\) 都小。

  2. \(C^m_n=\frac{n\times (n-1)\times \cdots \times (n-m+1)}{m\times (m-1)\times \cdots \times 1}\)。

    问题:我们不可能把分子乘完再除以分母,会爆的。

    方法一:\(C^m_n = \displaystyle \prod_{i=1}^m \frac{n-i+1}{i}\)。 但是这个方法可能会爆。

    方法二:求出 \(1\sim m\) 的逆元。然后把除换成乘。一路直接乘过去,边乘边模。

    复杂度:算一次 \(O(m)\)。

    适用情况:\(m\) 小。

  3. \(C^m_n=\frac{n!}{(n-m)!m!}=n!(m!)^{-1}[(n-m)!]^{-1}\)。

    只要能求出阶乘的逆元,就可以 \(O(1)\) 计算。

    我们考虑 \((n!)^{-1}\) 和 \([(n+1)!]^{-1}\) 互相转化。

    \(1\equiv (n+1)!\times [(n+1)!]^{-1} \equiv n!\times (n+1)[(n+1)!]^{-1}\)。

    所以 \((n!)^{-1}\equiv [(n+1)!]^{-1}(n+1)\)。

    我们先欧拉函数暴力计算 \(n!\) 的逆元,然后从大往小推出所有阶乘逆元。

    注意:我们这里是可以从 \(n+1\) 推 \(n\),而不是 \(n\) 推 \(n+1\)。

    code

    优点:\(O(n)\) 预处理之后,每次询问 \(O(1)\)。

    复杂度:\(O(n)\)。

    适用场景:\(O(n)\) 可行,需要多次查询。

  4. 卢卡斯定理(Lucas)

    二项式定理:\((a+b)^n=\displaystyle \sum_{i=0}^n C^i_n a^{n-i}b^i\)。

    引理:对 \(k:1\sim(p-1)\),\(p\) 为质数,\(p\mid C^k_p\)。

    引理证明:\(C^k_p=\frac{p!}{k!(p-k)!}\),分子有一个 \(p\),分母没有 \(p\)。

    卢卡斯定理:\(C^m_n\equiv C^{m/p}_{n/p}\times C^{m\%p}_{n\%p} \pmod p\)。

    (若 \(C_n^m\) 中 \(m>n\),则 \(C_n^m=0\))

    证明:

    记 \(n=ap+b,m=kp+t\;(0\leq b,t < p)\)。

    \((1+x)^n=C_n^0x^0+C_n^1x^1+\cdots+C_n^mx^m+\cdots+C_n^nx^n.\)

    又 \((1+x)^n=(1+x)^{ap+b}=(1+x)^{p^a}\times (1+x)^b\;\;\;\;(1).\)

    而 \((1+x)^p=C_p^0x^0+C_p^1x^1+\cdots+C_p^px^p\equiv C_p^0+C_p^px^p\)。

    所以 \((1)\equiv (1+x^p)^a\times (1+x)^b\equiv [C_a^0(x^p)^0+C_a^1(x^p)^1+\cdots+C_a^k(x_p)^k+\cdots][\cdots+C_b^tx^t+\cdots].\)

    发现 \(x\) 的 \(kp+t\) 次项,一定是从左边括号选出 \(kp\) 次项,右边括号选出 \(t\) 次项,然后相乘得出的。

    所以 \(x\) 的 \(kp+t\) 次项的系数一定是 \(C_a^k\times C_b^t\)。

    而从二项式定理的展开中知道,\(x\) 的 \(m=kp+t\) 次项的系数应该是 \(C_n^m\)。

    所以 \(C_n^m=C_a^k\times C_b^t=C_{n/p}^{m/p}\times C_{n\%p}^{m\% p}\)。

    证毕。

    复杂度:\(O(p\log_p^{\;n})\)。

    适用场景:\(n,m\) 非常大,\(O(p)\) 可行。或者 \(n,m\geq p\),不能直接求逆元(不能保证互质),用卢卡斯定理转化。

数三角形

三角形个数 = 任取三个点的方法数 - 三点共线个数。

总数:\(C^3_{(n+1)(m+1)}\)

行的三点共线:\((n+1)C^3_{(m+1)}\)

列的三点共线:\((m+1)C^3_{(n+1)}\)

斜的:

考虑枚举所有点,对于一个点,枚举所有斜率,看这条线上有多少个点,然后用组合数求出来。

但是发现一个斜率可能有很多个点所得出的答案一样。

于是我们改一下顺序:先枚举所有斜率,然后对于所有可以放上这个斜率的点,求出这个斜率上所有点,然后再减去。

斜率可以看做一个长方形的对角线。于是我们枚举这个长方形的长 \(i\) 和宽 \(j\)。那么可以作为长方形左上角的点就有 \((n+1-i)(m+1-j)\) 个。

在每一个长 \(i\) 宽 \(j\) 的长方形对角线上,一共有 \(gcd(i,j)+1\) 个格点。(仪仗队)因此,取左上角、右下角和对角线中间 \(gcd(i,j)-1\) 个点中任意一个点都能组成一组三点共线,并且每一组之间不会重复。

另外,还要注意,长方形有两条对角线,所以每次减的时候要减两份。

code

生成字符串

其实就是卡特兰数。

考虑把问题对应成一个 \(m\times n\) 的方格表(\(n\) 是横着的)。最初我们在左下角,现在要去到右上角,每次可以向右或者向上移动一格。

把向右移动一格看做是在前面放一个 1,向上移动一格看做是放一个 0。那么移动到右上角就相当于我们取完了所有 0 和 1。每条移动的路径都和一个字符串一一对应。

条件 “任何前缀中 1 的个数必须不少于 0”,就相当于从左下角画一条 45° 向右上角走的斜线,不能越过这条斜线。

把这条斜线整体上移一个,条件就变成了不能碰到这条斜线。

我们还是考虑总数减去不符合要求的数。

总数:\(C^m_{(n+m)}\),即从 \(n+m\) 步中选 \(m\) 个位置向上走。

不符合方案(碰到斜线):

把这个方格表的左边加一列,并把斜线往左下角延伸一个。此时的斜线就连到了新方格表的左下角。

考虑所有不符合的方案,一定存在第一个点,碰到了斜线。
我们把这个点之前进行的所有步,都关于这条斜线做对称。

这样我们就得到了一条新路径:从新表左下角的上面一格出发,走到右上角。

我们发现,每一条这种路径,都与一条不符合要求的路径一一对应。并且,这种路径一共走了 \(n+m\) 步,其中有 \(m-1\) 步向上。

所以,这种路径的数量是 \(C^{(m-1)}_{(n+m)}\)。

因此,答案就是 \(C^m_{(n+m)} - C^{(m-1)}_{(n+m)}\)。

code

可重组合

插板法。

\(k\) 种里面选 \(x\) 个。考虑第 \(i\) 种选了 \(x_i\) 个。就是解 \(x_1+x_2+\cdots+x_k=x\) 的非负整数解。

\(C_{x+k-1}^{k-1}\),也可以说是 \(C_{x+k-1}^x\)。

建设城市

注意:\(n,n+1\) 之间没有要求。

两种情况:\(x,y\) 一左一右,或者 \(x,y\) 同侧。

  1. 一左一右。

    假设高度 \(k\)。则 \(1\sim x-1\) 的楼高度取值 \(1\sim k\)。

    我们发现,只要取出了 \(x-1\) 个高度,其排列方式已经固定了。

    所以,这就是一个 “可重组合”。从 \(k\) 种里面选 \(x-1\) 个,答案 \(C^{x-1}_{k+x-2}\)

    之后另外三个部分都差不多,求完四块之后全部相乘,就是 \(x,y\) 高度为 \(k\) 的方案数。

    复杂度 \(O(n+m)\)。因为 \(O(n)\) 预处理组合数(第三种),\(O(m)\) 枚举 \(x,y\) 的高度。

  2. 同侧。

    显然,同左和同右是对称的。

    这种其实就是只有三个部分——\(x,y\) 中间夹着的一定高度都是 \(k\)。

【容斥原理】

有三个集合 \(A,B,C\)。现在想要知道 \(|A\cup B \cup C|\)。

\(|A\cup B\cup C|=|A|+|B|+|C|-|A\cap B|-|B\cap C|-|A\cap C|+|A\cap B\cap C|\)。

例如,\(1\sim n\) 中 \(2\) 或 \(3\) 或 \(5\) 的倍数有几个,就是 \(n/2+n/3+n/5-n/6-n/15-n/10+n/30\)。(下取整)

容斥原理:

\(|A_1\cup A_2\cup \cdots \cup A_n|=\displaystyle \sum |A_i|-\displaystyle \sum_{i\neq j} |A_i\cap A_j|+\sum |A_i\cap A_j\cap A_k|-\cdots.\)

证明方法考虑归纳法。


容斥原理的题目一般长这样:

符合条件 \(t_1,t_2,\cdots,t_n\) 至少一个的方法数。(1)

对 \(t_1,t_2,\cdots,t_n\) 的不符合的方法数。(2)

符合 \(t_i\) 的情况,记为 \(A_i\)。全集记为 \(S\)。

(1):答案为 \(A_1\cup A_2\cup \cdots \cup A_n\)。

(2):答案为 \(C_S(A_1\cup A_2\cup \cdots \cup A_n)\)。

而全集一般都很好求。所以情况(1)和情况(2)可以视为等价的。

不妨称 \(t_i\) 为 “基本条件”,\(A_i\) 为 “基本集合”。


容斥原理的代码:

写一个子集枚举,传参数记录选了多少个集合交起来。然后根据参数判断当前的答案是正是负。


无平方数

记 \(p_i\) 为第 \(i\) 个质数,\(2^{50}\) 内有 \(k\) 个质数(\(k\) 大概是 \(3\times 10^7\))。\(A_i\) 为符合 “是 \(p_i^2\) 的倍数” 条件的集合。

则 \(A_1\cup A_2\cup \cdots\cup A_k\) 为所有 “非 squarefree” 的数。

\(|A_i|=[\displaystyle\frac{2^{50}}{p_i^2}]\),\(|A_i\cap A_j|=[\displaystyle\frac{2^{50}}{(p_ip_j)^2}]\),\(|A_i\cap A_j\cap A_t|=[\displaystyle \frac{2^{50}}{(p_ip_jp_t)^2}]\)……

这个并集是不好算的,但是交集很简单。

我们可以搜索——搜索出所有若干个质数相乘的所有次数为 \(1\) 的数,并同时记录每个数是由多少个质数乘起来的。(当然,质数乘起来必须 \(\leq 2^{25}\),否则平方就炸掉了。)

code

硬币购物

如果只有一次询问,可以直接多重背包加单调队列优化,但是有多次询问。

记 \(t_i\) 为 “第 \(i\) 种硬币使用超量”,\(A_i\) 为对应集合。

\(t_1\cup t_2\cup t_3\cup t_4\) 为 “至少有一种硬币超量”,是所有不符合条件的情况。

记 \(dp[x]\) 为凑 \(x\) 面值,每种硬币随便用的方法数。(完全背包)

\(|A_i\cap A_j|=dp[s - (d_i+1)c_i-(d_j+1)c_j]\),因为先把 \(i,j\) 两种取到保证超量。

因为硬币种数很少,所以每次询问求一次容斥都没压力。

一个东西选超量:先把它取完,再多取一个,最后随便选。

分特产

如果不要求每人至少拿一个,我们可以先把第一个分给所有人,然后分第二个…… 分每一个之间相互独立,分步计数。

如果要求每人至少一个,当前每个人是否拿到了就会影响后面的特产分发,不能分步计数。

但是,我们可以考虑反面至少有一个人没有特产。

\(t_i\):第 \(i\) 个人没拿到特产。

想要的:\(A_1\cup A_2\cup \cdots \cup A_n\) 的补集。(所有同学都分到了)

\(|A_i|=\) 所有特产分给另外 \(n-1\) 个人的方法数。

\(|A_i\cap A_j|=\) 所有特产分给另外 \(n-2\) 人方法数 \(=\prod C_{a_i+(n-2-1)}^{a_i}\)。(隔板法)

另外注意到,无论是哪两个同学没分到,答案都相等。所以我们不需要真的枚举所有子集。

一个人没分到:把所有东西都分给别人。

染色问题

分步考虑三个条件。

  1. \(t_i\) 为第 \(i\) 种颜色不用。想要的是所有集合并起来的补集:所有颜色都用过。

    \(|A_i\cap A_j|=\) 剩下 \(C-2\) 种颜色随便染的方法数。

    复杂度贡献乘 \(C\),无论是选第 \(1,2\) 种颜色,还是选第 \(3,4\) 种颜色,答案都是一样的。

  2. 有 \(k\) 种颜色可选。\(t_i\) 为第 \(i\) 行无色。所有集合的并集的补集:每一行都有色。

    \(|A_i\cap A_j|=n-2\) 行 \(m\) 列染色,不要求每行有色。

  3. \(x\) 行 \(y\) 列 \(k\) 种颜色,只需每列有色。不考虑另外两个条件。

    \([(k+1)^x-1]\) 是某一列有色的情况数:一列 \(x\) 个,每个有 \(k+1\) 种染色方式(包括不染),去掉每一个都不染的情况。

    一共 \(y\) 列,\([(k+1)^x-1]^y\) 种方法。

用两次容斥,去掉两个条件。

//用x种颜色染色的方法,仍要求行列非全无色,但x种颜色不必都用过
long long cnt(long long x) {
	long long ans = 0;
	// 其中i行可以有颜色,即某n-i行无色
	for (long long i = n, t = 1; i >= 1; i--, t *= -1)
		ans = (ans + fpow((fpow(x + 1, i) - 1)/*一列全部方案减去一种全无色*/, m)/*所有列非全无色*/ * t * cmb(n, i) % p + p) % p;
	//X种颜色不必都用过(但每行每列必须有色)=X种颜色涂n行(颜色不必都用每行不必有色但每列必须有色)-X种涂n-1行(颜色不必都用每行不必有色但每列必须有色) + X种颜色涂n-2行(颜色不必都用每行不必有色但每列必须有色)- ....
	 
	//X种颜色涂i行(颜色不必都用,每行不必有色,但每列必须有色)已经足够简单,方法数是 [(X+1)^i - 1]^m
	return ans;
}

for (long long i = c, t = 1; i >= 1; i--, t *= -1)
		ans = ((ans + cmb(c, i) * cnt(i) * t) % p + p) % p;
//ans = C种颜色不必都用过(但每行每列必须有色) - C-1种颜色不必都用过(但每行每列必须有色) + C-2种颜色不必都用过(但每行每列必须有色) - .... 

错排问题

\(f(n)=(n-1)(f(n-2)+f(n-1))\)。

卡特兰数

考虑所有符合条件的路径,一定有 “第一个碰到斜线的地方”。(至少在终点碰到了)

\(ans=\) 从起点到这个地方 \(\times\) 从这个地方到终点。

这两个部分分别是更小的卡特兰数。

当出入栈序列固定,最终序列也就确定了。

出入栈序列只要求每个前缀中,出栈个数小于等于入栈。

这就是卡特兰数。

卡农

简化题意:

给出一个音阶集合 \(S=\{x_1,x_2,...,x_n\}\)。记其非空子集(片段)为 \(S_1,S_2,...,S_{2^n-1}\)。

要求选出 \(m\) 个非空子集 \(S_{t_1},S_{t_2},\cdots,S_{t_m}\),要求每个音阶在选出的非空子集中出现偶数次 且 \(t_1,t_2,\cdots,t_m\) 互不相同。

问有多少组 \(\{t_1,t_2,\cdots,t_m\}\)。

三个条件:不同、非空、\(x_i\) 出现偶数次。

设 \(dp[i]\) 为选 \(t_1\sim t_i\) 并符合条件的方法数。

分步。

  1. 任选 \(t_1\sim t_{i-1}\),只要求不同非空即可,\(\displaystyle C_{2^n-1}^{\,i-1}\)。

  2. 选 \(t_i\)。对于一个音阶 \(x_a\),如果在选出的 \(t_1\sim t_{i-1}\) 中出现奇数次,必须选;否则必须不选。

    考虑特殊情况:\(t_i\) 和之前的重复了,或者是空集。

    1. \(S_{t_i}\) 空,意味着前 \(i-1\) 个已经满足了所有条件。

      因为 “\(i\) 个有一个空集” 和 “\(i-1\) 个刚好满足所有条件” 一一对应,所以一共有 \(dp[i-1]\) 个这种情况。

    2. \(S_{t_i}\) 和之前的重复了(显然这种情况和 1 类没有重复),意味着把 \(S_{t_i}\) 和与它重复的集合去掉,又可以满足所有条件。

      考虑这个对应关系。

      显然 \(i\) 个片段含一对重复,可以唯一对应到 \(dp[i-2]\) 里面。

      但是 \(dp[i-2]\) 对应到很多个 “\(i\) 个含一对”,因为 \(i-2\) 含的一对相同片段有 \([(2^n-1)-(i-2)]\) 种选择。

      所以最后有 \(dp[i-2]\times [(2^n-1)-(i-2)]\) 种这个情况。

标签:种颜色,所有,组合,cup,cap,基础,times,cdots
From: https://www.cnblogs.com/FLY-lai/p/18016079

相关文章

  • 基础图论笔记
    二分图  染色法  例题ACwing860-染色法判断二分图(染色法)-CSDN博客给定一个n个点m条边的无向图,图中可能存在重边和自环。请你判断这个图是否是二分图。输入格式第一行包含两个整数n和m。接下来m行,每行包含两个整数u和v,表示点u和点v之间存在一条边。输出格式如......
  • Lag-Llama:第一个时间序列预测的开源基础模型介绍和性能测试
    2023年10月,我们发表了一篇关于TimeGPT的文章,TimeGPT是时间序列预测的第一个基础模型之一,具有零样本推理、异常检测和共形预测能力。虽然TimeGPT是一个专有模型,只能通过API访问。但是它还是引发了对时间序列基础模型的更多研究。到了2024年2月,已经有了一个用于时间序列预测的开源......
  • 《从基础认识相对论的错误》 回复
    《从基础认识相对论的错误》      https://tieba.baidu.com/p/8895510201     这帖是你昨天发的, 10天前,你发了  《相对论对物理理论的影响是什么?》   https://tieba.baidu.com/p/8885351309  , 半年前,  我发过《@东方已晓的反相观点》......
  • python基础学习6-第三方模块
    自定义模块优先级大于系统模块模块分为系统模块,自定义模块,第三方模块导入方式import模块名称[as别名]from模块名称import变量/函数/类*包的导入import包名.模块名as别名form包名import模块名as别名form包名.模块名import函数/变量/类*主程序运行i......
  • leetcode 17 电话号码的字母组合
     解题关键点:用递归方法classSolution{public:vector<string>mapping={"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};voidcom......
  • Java基础
    java基础一、注释二、标识符和关键字关键字:标识符Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。标识符注意点:所有的标识符都应以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始首字符之后可以是字母(A-Z或者a-z),美元符($)、下划线(_)或数字的任何字符组合......
  • DFS基础与回溯
    回溯法简介回溯法一般使用DFS(深度优先搜索(递归))实现,DFS是一种遍历或搜索图,树或图像等数据结构的算法。上述数据结构不保存下来就是回溯法。常见的是搜索树,排列型搜索树(节点数一般为n!)与子集型搜索树(节点数一般为2n)。DFS从起始点开始,沿着一条路尽可能深入,直到无法继续回溯到上......
  • 基础数据结构笔记
    链表与邻接表:树与图的存储 单链表  画个图就很好理解了   例题826.单链表acwing——826.单链表_awcing826-CSDN博客实现一个单链表,链表初始为空,支持三种操作:(1)向链表头插入一个数;(2)删除第k个插入的数后面的数;(3)在第k个插入的数后插入一个数现在要......
  • 第二章 语法基础
       目  录1.第一个Python程序 2.数据与数据类型 3.数据类型转换 4.标识符 5.变量 6.常量 7.Python运算符 8.表达式 9.语句 10.实例: 语法基础    任何一段计算机程序都是由一组计算机能够理解的指令构成,其中每条指令都表现为遵循......
  • 2024牛客寒假算法基础集训营3
    M题智乃的36倍数(normalversion)错解幂运算写成了乘~#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'#defineintlonglong#definedebug(x)cout<<x<<""<<endl;#define_debug(a,n)for(inti=0;i<n;i++)......