(浙江金华)Day 1 组合数计数

Day 1 组合计数

1.组合数

(1)、C(n,m) 读作n选m,二项式系数 :

5bbaba7729a97.png
5bbaba7711bb8.png
5bbaba772857b.png

(2)、n个东西里选m个的方案数 不关心选的顺序:

5bbaba7720edf.png
5bbaba77386d6.png
5bbaba7736de1.png

(3)、二项式系数--->多项式系数:

(x+y+z)^n 5bbac5cd07fd7.png

2.组合数计算

(1)、递归、纯相加、带初始值的公式(递推:考虑选不选最后一个元素):

5bbabbd74984e.png

(2)、初值(O(n^2)预处理):

5bbabbd761fba.png

(3)、运算(复杂度O(n)):

5bbabbd760831.png
可以保证每一步运算都是整数;
保证单次O(n)计算组合数模任意数;
可以记录组合数因子出现次数cnt(x);
若知道每个数x的最小质因子mnp(x),从后往前扫 对于每个合数 将cnt(x/mnp(x))+=cnt(x) cnt(mnp(x))+=cnt(x),最后可以得到质因数分解形式 由于质数个数O(n/ln(n)) 。

优化:(对于质数 可以O(n)预处理 O(1)求值 , N>INF, Lucas定理 注意模数必须是质数)
5bbabbd74b249.png
对于非负整数m, n和素数p,下面的同余关系成立:
5bbabbd75f0f2.png

Ⅰ.如果模数也很大(n,m <= 1e9,P = 1e9+7)就分块打表,为了快速获得x!(x的阶乘),设置B 打表B! (2B)! (3B)! …每次查询一个x!,只需要用表中最接近的值O(B)计算,表的长度O(P/B)

Ⅱ.如果模数不是定值,以后再说.......

3.组合数求前缀和

(1)、过程大致如下:

5bbabbd734036.png5bbabcf4aa623.png

可以化简为:(S无法快速计算 但是可以递推)

5bbabcf4a8da3.png

多组询问的情况下可以使用莫队算法,也可以分块预处理出所有m是B的倍数的S

4.组合数组合意义

(1)、概念:

①共有5bbabd922f1c0.png种方式从n元素中选取k项;
②共有5bbabd92444c0.png种方式从一个n元素中选取(容许重复选取)k元素建立多重集;
③共有5bbabd9247399.png个字符串包含k个1和n个0;
④共有5bbabd922de6e.png个字符串包含k个1和n个0,且没有两个1相邻;
⑤卡特兰数是:5bbabe6b06b7b.png

(2)、组合意义:

将n个可区分的元素放进r个可区分的容器里 第i个容器中放了k_i个的方案数

(3)、性质:

一个没:5bbac7f77763a.png
对称性:5bbac7f778cf5.png

(4)、例题:

例1:一个网格纸 每次只能往右或往上走
5bbabe6b39abc.png
只向右或向上走的方案数为:C(n+m,m)或 C(n+m,n);
证明:
5bbabe6b20fc8.png5bbabe6b1fd97.png

例2:
计算方程的整数解个数 一共有M个未知数要满足:5bbabd9242bd7.png
则:解的数量为C(N+M-1,M-1) (插板法).如果未知数有下限,直接将N减掉下限的和

5.组合数例题

例1:

一个正n边形 将其所有对角线连起来 一共有多少个交点(保证n是奇数 不存在三条对角线共点)。
∵4个点确定一个交点   ∴C(n,4) .
    

例2([AGC001E] BBQ Hard):

烧烤硬 问题陈述:

史努克正在举行另一场烧烤聚会。 这次,他要做一份烤串饭。他有一堆烤串饭盒。第i-th串肉套餐包含一个串,Ai片牛肉和Bi片青椒。这些包装里的所有串都是不同的,可以区分,而所有的牛肉片和青椒片,分别是不能区分的。为了做一顿串肉饭,他从他的串肉饭包里挑了两个,然后从选择的包里拿出所有的东西,也就是两个串和一些牛肉或青椒。(剩下的烤串套餐将不使用。)然后,所有的食物碎片都以任意顺序,一个一个地串在两根烤肉串上。

5bbabe6bb34c2.png

他可以用多少种不同的方法做一顿烤串饭?当且仅当所使用的串组不同或食物的顺序不同时,制作串餐的两种方法是不同的。因为这个数可以非常大,所以求它的模1e9+7。

问题简化:
给定a,b数组,要求下面式子模1000000007:5bbabd9245cc2.png5bbabf0fe3ed8.png

思路:
考虑把组合数描述成坐标。 那么这就是(−ai,−bi)到(aj,bj) ,中途只能向上或向左走的路径条数。 考虑在坐标系上点上所有点,直接来一波dp算方案:

    f[i][j]=f[i][j]+f[i−1][j]+f[i][j−1];
        

如果本来就有一个点就初始化那个点为1。考虑这样算算重了自己的三象限坐标到自己一象限坐标的方案,所以要减去自己到自己的方案。 也就是说直接拿自己的组合数去减即可.

代码实现:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;
const int M=2e3+10;

int n;
int a[N],b[N],f[M*2+1][M*2+1];
ll p[N],e[N],c[N];
ll ans;

inline int read() {
    int n=0,f=1;char ch=getchar();
    while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    while (ch<='9' && ch>= '0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
    return n*f;
}

inline ll C(ll x,ll y) {
    if(x<y) return 0;
    if(x==y || !y) return 1;
    return e[x]*c[y]%mod*c[x-y]%mod;
}

int main() {
    n=read();
    e[0]=p[1]=c[1]=c[0]=1,ans=0;
    for(int i=1;i<=(M<<2)+100;++i) e[i]=e[i-1]*i%mod;   
    for(int i=2;i<=(M<<2)+100;++i) {
        p[i]=(mod-(mod/i))*p[mod%i]%mod;
        c[i]=c[i-1]*p[i]%mod;   
    }
    for(int i=1;i<=n;++i) {
        a[i]=read(),b[i]=read();
        f[M-a[i]][M-b[i]]++;
        ans=(ans-C(a[i]*2+b[i]*2,a[i]*2)%mod+mod)%mod;
    }
    for(int i=1;i<=(M<<1);++i) {
        for(int j=1;j<=(M<<1);++j) {
            f[i][j]=(f[i][j]+f[i-1][j])%mod;
            f[i][j]=(f[i][j]+f[i][j-1])%mod;
        }
    }
    for(int i=1;i<=n;++i) ans=(ans+f[a[i]+M][b[i]+M])%mod;
    printf("%I64d\n",ans*p[2]%mod);
    return 0;
}
/*
3
1 1
1 1
2 1

26
*/

例3:
问题描述:
给你一棵n个节点的有根树。你要给每个节点分配一个1~n的数字,使得每个节点分配的数字不同,并且每个节点分配的数字都是它子树内最小的,求方案数。
考虑树形dp,dp(i)表示i这个子树分配1~sz(i)的方案数,转移:5bbbdc65eefc2.png
进一步推理可得:5bbc134145f28.png

6.基础组合问题

(1)、基础概念:

①.加法原理 要么A 要么B A和B不相交,一个整数可以属于[1,3]或[4,6] 那么共有6种可能

②.乘法原理 AxB A和B中各选一个,第一个整数属于[1,3] 第二个整数属于[1,2] 共有6种可能.

③.n个可区分的元素选k个排成一列 排列方法有n(n-1)(n-2)…(n-k+1)=n!/(n-k)!种.

(2)、例题:

题目描述:
n个未知数,给定每个数的上限a_i,问你有多少种方法使得这些未知数都是正整数且互不相同。输出方案数模1e9+7。(n<=1e5 1<=a_i<=1e9 30)
思路:

    考虑将a_i从小到大排序 依次确定未知数的值
    ANS=a_1*(a_2-1)*(a_3-2)*…*(a_n-(n-1))

(3)、一个很有用的计数原则:

一个由计数对象组成的集合S,要计算它的大小|S|,考虑如果我们找到一个集合T,使得S的元素与T的元素一一对应,那么|S|=|T|

(4)、一个推广:

如果S的每个元素对应到a个T中的元素,T的每个元素对应到b个S中的元素,那么有:
**a|S|=b|T| |S|=|T|*b/a**

(5)、例题:

题目描述:
n个可区分的元素围成一排 有多少种方案?

思路:

    S:n个元素的环排列        T:n个元素的排列
    S->T:对于一个环排列 将其旋转 可以得到n个不同的排列 即对应到T中的n个元素
    T->S:对于一个排列 只能被一个环排列旋转得到
    n|S|=|T|    |S|=|T|/n

7.Twelvefold way && 容斥原理

(1)、Twelvefold way 描述:

n个有标号/无标号的球分给m个有标号/无标号;盒子有三种限制:

A)无限制
B)每个盒子至少有一个球
C)每个盒子至多有一个球

共12种问题:
为了方便 将有标号记为L(labelled) 无标号记为U(unlabelled) 那么一个问题可以用缩写代替

(2)、Twelvefold way(①~⑦)

①(LLA)n个有标号的球分给m个有标号的盒子(m^n)

②(ULA)n个无标号的球分给m个有标号的盒子,等同于方程的整数解个数 C(n+m-1,m-1)

③(ULB)n个无标号的球分给m个有标号的盒子没有空盒,等同于方程整数解个数 C(n-1,m-1)

④(LLC)n个有标号的球分给m个有标号的盒子 每个盒子至多放一个球(m!/(m-n)!)

⑤(ULC)n个无标号的球分给m个有标号的盒子 每个盒子至多放一个球C(m,n)

⑥(LUC)n个有标号的球分给m个无标号的盒子 每个盒子至多放一个球[n<=m]

⑦(UUC) n个无标号的球分给m个无标号的盒子 每个盒子至多放一个球[n<=m]

(3)、容斥原理

①.基础:
5bbc7ae26209f.png
5bbc7ae26cb66.png
5bbc7ae27a668.png
5bbc7c630dca8.png

②.容斥原理基础应用(例题):
1~100中既不被2整除也不被3整除也不被5整除的数有多少个?

A=被2整除的数的集合   
B=被3整除的数的集合
C=被5整除的数的集合

5bbc7d00d2987.png
∴|A∪B∪C|=50+33+20-16-10-6+3=74 ∴100-74=26

(4)、Twelvefold way(⑧~⑨)

⑧(LLB)n个有标号的球划分给m个有标号的盒子 不能有空盒5bbc84d75132b.png

⑨(LUB) n个有标号的球划分给m个无标号的盒子 不能有空盒 5bbc844eb8a31.png

8.Twelvefold way && 第二类斯特林数

(1)、第二类斯特林数简介:

就以(LUB)和(LLB)为例来简单说一下吧:
(LUB) 即n个有标号的球划分给m个无标号的盒子不能有空盒,(LLB) S(n,k)k!

(2)、递推式(考虑最后一个球是否独立给一个盒子):

5bbc8e9ae1713.png
5bbc8eef01abf.png

(3)、Twelvefold way (⑩)

(LUA)n个有标号的球划分给m个无标号的盒子,枚举有几个盒子被分配了

S(n,0)+S(n,1)+…+S(n,m)

9.Twelvefold way && 划分数

(1)、划分数(p(n,k))基础知识:

① n=x_1+x_2+…+x_k,将n划分为k个正整数的方案数 方案与x的顺序无关
② 递推式:p(n,k)=p(n-k,k)+p(n-1,k-1) (考虑最小的数是否为1)

(2)、Twelvefold way(最后两个)

11.(UUB)n个无标号的球划分给m个无标号的盒子 每个盒子至少有一个球 p(n,m)

12.(UUA)n个无标号的球划分给m个无标号的盒子,枚举有几个盒子被分配了,p(n,1)+p(n,2)+…+p(n,m) ,p(n+m,m).

(3)、Twelvefold way(完结篇)

5bbc9369e9c37.png
(PS:这里的p_k(n) 定义为至多划分为k个的划分数)

14.卡特兰数

(1)、基础:

5bbc95f4336d8.png
①.1,1,2,5,14,42,132,429,1430…

②.组合应用:
有2n个括号的合法括号序列个数(递推式相同)
如:C(3)=5 ((())) ()(()) ()()() (())() (()())

③.有n个非叶子节点的满二叉树的个数

④.不超过对角线的NE 网格路径的个数(或算不经过y=x+1这条直线的路径个数),具体来说,就是考虑碰到了这条直线的路径,我们将其之前的路径按照这条直线对称,那么可以对应到一个(-1,1)到(n,n)的路径, 又由于每个(-1,1)到(n,n)的路径都必然经过y=x+1这条直线,所以可以对应到一个(0,0)到(n,n)且碰到了y=x+1这条直线的路径;由之前提到的计数原则得到:(0,0)到(n,n)且碰到了y=x+1的路径条数与(-1,1)到(n,n)的路径条数相等,5bbc971b8d77f.png
5bbc973f6cf4e.png

15.容斥原理进阶 && 容斥原理进阶练习

(1)、容斥原理可以与之前提到计数方法结合:

给定上界和下界的方程的整数解问题5bbc97b1c7723.png
下界可以直接从N减掉,不满足X<=B  X>=B+1,考虑容斥一个子集不满足上界后,所有变量只剩下界,可 以 直 接 组 合 数 计 算 方 案 数,由于最后方案数只和被减掉多少以及容斥系数有关,当未知数个数多但是上界小的时候,可以使用类似背包的动态规划优化.

(2)、例题:

例1:
题目描述:
问你有多少个n位数,满足以下要求:

1)这个数是回文串
2)奇数位的和等于偶数位的和

输出答案模1e9+7,n<=1e6

思路:
Ⅰ、位数是偶数 答案为10^(n/2);
Ⅱ、位数是奇数:

    解:设 abcdcba    
        则有:2a+2c=2b+d;
        每个未知数的范围为[0,9].
        移项后 得到:2x_1+2x_2+2x_3+….-2y_1-2y_2-2y_3-…-z=0
        设有k1个正项 k2个负项
        所有未知数的范围为[0,9]
        首先z可以枚举
        发现负项的取值范围为 [-9,0] 不妨将每个负项加9
        这样式子就变成了
        2x_1+2x_2+2x_3+…+2(9-y_1)+2(9-y_2)+…-z=18k2
        此时除了z外所有未知数是等价的
        问题就变成了 有k1+k2个值域在[0,9]的未知数 问他们的和为S有多少种方案
        发现这是一个有上界的方程的整数解的问题
        可以O(k1+k2)(即O(n))枚举有几个数大于上界
        最终复杂度O(10n)

例2:
题目描述:
给定n个障碍点(x_i,y_i) 求有多少条不经过障碍点的(0,0)到(X,Y)的NE 网格路径(n<=5000 0<=x_i,y_i,X,Y<=100000)。

思路:
dp(i)表示从(0,0)到(x_i,y_i)不经过除了终点外的障碍点的方案数
5bbc9a3a62f6b.png
转移:枚举第一个碰到的障碍点将终点视为第n+1个障碍点 那么答案为dp(n+1)(PS:注意转移不会成环)

例3:
问题描述:
n种珠子,第i种有a_i个。将它们排成一列,要求相邻的两个珠子种类不同,问有多少种方案。

思路:

解:设S=a_1+a_2+…+a_n
    原题条件:所有S-1对相邻的珠子种类不同难以直接容斥
    转化:考虑某一种类的所有a_i个珠子 a_i-1对相对位置上相邻的珠子不相邻 
    对于某一种类 容斥后变为某些相对位置上相邻的珠子相邻 即这些珠子连成一段
    不妨将这些珠子看做一个整体 那么我们可以把段数相同的情况合并 记录段数一定时 容斥系数的和记容斥后剩余x段的容斥系数的和为s_x
    考虑如何计算对整体容斥的贡献
    x段珠子与x个珠子在对排列方案数的贡献是相同的
    每一类相当于变成:若看做1个珠子时 贡献系数为s_1 看做2个珠子时 贡献系数为s_2 …
    总答案就是 枚举每类珠子被看做了几个珠子 计算排列成一列的方案数 将方案数乘上贡献系数s的积加入答案
    可以使用类似背包的dp

例4:
问题描述:
n个不同的正整数排成一个序列,其中数字i出现次数为ci。对于每一个这样的序列,定义他的权值如下:
Ⅰ、将这个序列首尾相接放在一个圆上。把这些数字分成若干相邻的段,使得每段里都是在圆上相邻的数字,任意两段没有公共的元素,每一段中的数字都相同,相邻段中的数字不同。这个序列的权值定义为所有段的长度之积。求所有序列的权值和对1000000007取膜。(PS:虽然计算序列权值的时候是圆排列,但互为循环排列的不同序列仍然认为是不同的,如(1,2,1,2)和(2,1,2,1)就认为是不同的序列

思路:

    解:
        先考虑序列上的问题,用之前介绍的方法做即可。
        不同的是 我们不仅需要考虑容斥系数 还要考虑段的权值
        可以使用dp计算出段数一定时 容斥系数乘权值的和 作为贡献系数
        后面与之前介绍的方法完全一样
        考虑如何处理环的问题
        注意这题序列的开头与结尾如果数字相同 也视为同一段
        可以考虑使用之前说的计数原则:
        S:本题中描述的序列(代表一个环)包含d段数字1 
        T:一个开头为数字1,结尾不为数字1的序列 包含d段数字1 
        T->S:旋转n次,共对应到n个S中的元素
        S->T:一共被d个T中的元素旋转到
        所以得到n|T|=d|S|   |S|=|T|*n/d
        所以得到n|T|=d|S|   |S|=|T|*n/d
        由于我们计算的是T的集合里所有元素的代价和
        并且S和T的对应关系并不会改变代价
        所以我们只要算出所有T的元素的代价除以d(即数字1的段数)的和,再乘上n就可以得到S中所有元素的代价和,即最终答案

16.小练习(未完结...)

(1)、AGC018E

题目描述:
给定三个不相交的矩形A(X1,Y1)-(X2,Y2) B(X3,Y3)-(X4,Y4) C(X5,Y5)-(X6,Y6),求有多少条NE lattice path从A中某个点出发 中途经过选定的B中的某个点 最终到达C中的某个点,ABC中选定的点不同 lattice path也视为不同( 1<=X1<=X2<X3<=X4<X5<=X6<=1000000).

(2)、某个题1:

题目描述:
飞机上有n个座位排成一列,共有m个乘客。你需要为每个乘客选定一个座位以及进入飞机的入口(要么从前门进 要么从后门进) 每个人会从指定的入口走向指定的座位,如果座位已经被占了,他就会继续向前走直到一个没有被占的座位,并占据那个座位。如果他直到飞机的一端都没有找到空座位,他就会生气。求有多少种分配的方案,使得没有人会生气。输出方案模1e9+7(n,m<=1e6).

(3)、某个题2:

题目描述:
一共n+m个判断题,告诉你答案有n个YES m个NO。现在这n+m个题以随机的顺序依次给你,每道题你回答后就会告诉你答案是否正确。你使用最优策略回答问题。求期望你答对的题数。输出答案模1e9+7(n,m<=1e6).

转载于:https://www.cnblogs.com/Darkpurple/p/9753205.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值