news 2026/5/28 4:33:56

【模板:求组合数】信息学奥赛一本通 1648:【例 1】「NOIP2011」计算系数 | 1866:【11NOIP提高组】计算系数 | 洛谷 P1313 [NOIP 2011 提高组] 计算系数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【模板:求组合数】信息学奥赛一本通 1648:【例 1】「NOIP2011」计算系数 | 1866:【11NOIP提高组】计算系数 | 洛谷 P1313 [NOIP 2011 提高组] 计算系数

【题目链接】

ybt 1648:【例 1】「NOIP2011」计算系数
ybt 1866:【11NOIP提高组】计算系数
洛谷 P1313 [NOIP 2011 提高组] 计算系数
ybt 1648没有指明k kk的范围,在ybt 1866, 洛谷P1313中都以指明k ≤ 1000 k\le1000k1000

【题目考点】

1. 加法原理与乘法原理

加法原理:完成一件事的方法有n nn类,第i ii类包括m i m_imi种不同的方法,而且这些方法不重合,则完成这件事共有N NN种方法,满足:N = m 1 + m 2 + ⋯ + m n N=m_1+m_2+⋯+m_nN=m1+m2++mn
口诀:分类相加
乘法原理:完成一件事需要n nn个步骤,其中第i ii个步骤有m i m_imi种不同的完成方法,而且这些步骤互不干扰,则完成这件事共有N NN种方法,满足:N = m 1 m 2 ⋯ m n N=m_1m_2⋯m_nN=m1m2mn
口诀:分步相乘

2. 排列组合

排列:从n nn个不同的元素中,取m ( m ≤ n ) m (m≤n)m(mn)个元素,按照一定顺序排成一列,称为从n nn个不同元素中取出m mm个元素的一个排列,这样的排列的个数称为排列数,记为P n m P_n^mPnmA n m A_n^mAnmP n n P_n^nPnn称为n nn个元素的全排列。
P n m = n ( n − 1 ) . . . ( n − m + 1 ) = n ! ( n − m ) ! P_n^m=n(n-1)...(n-m+1)=\dfrac{n!}{(n-m)!}Pnm=n(n1)...(nm+1)=(nm)!n!

第1步:从n nn个元素中取出一个元素,共n nn种取法。
第2步:从n − 1 n-1n1个元素中取出一个元素,共n − 1 n-1n1种取法。

m mm步:从n − m + 1 n-m+1nm+1个元素中取出一个元素,共n − m + 1 n-m+1nm+1种取法。
根据乘法原理,有:P n m = n ( n − 1 ) . . . ( n − m + 1 ) P_n^m=n(n-1)...(n-m+1)Pnm=n(n1)...(nm+1)

组合:从n nn个不同的元素中,取m ( m ≤ n ) m(m\le n)m(mn)个元素,组成一个集合,称为从n nn个不同元素中取出m mm个元素的一个组合,这样的组合的个数称为组合数,记为C n m C_n^mCnm

C n m = P n m P m m = n ( n − 1 ) . . . ( n − m + 1 ) m ( m − 1 ) . . . 1 = n ! ( n − m ) ! m ! C_n^m=\dfrac{P_n^m}{P_m^m}=\dfrac{n(n-1)...(n-m+1)}{m(m-1)...1}=\dfrac{n!}{(n-m)!m!}Cnm=PmmPnm=m(m1)...1n(n1)...(nm+1)=(nm)!m!n!

n nn个元素中取出m mm个元素可以分为两步
第一步:从n nn个元素中取出m mm个元素的一个组合,方案数为C n m C_n^mCnm
第二步:将这m mm个元素进行全排列,方案数为P m m P_m^mPmm
根据乘法原理,有P n m = C n m P m m P_n^m=C_n^mP_m^mPnm=CnmPmm
因此C n m = P n m P m m C_n^m=\frac{P_n^m}{P_m^m}Cnm=PmmPnm

C n m = C n n − m C_n^m=C_n^{n-m}Cnm=Cnnm,一般用于简化计算过程。
特殊地:C n 0 = C n n = 1 C_n^0=C_n^n=1Cn0=Cnn=1
m > n m>nm>n时,不存在从n nn个数中取出m mm个数的方案,C n m = 0 C_n^m=0Cnm=0

n nn个元素中取出m mm个元素拿走,和在n nn个元素中取出n − m n-mnm个元素留下的方案数是相同的。

杨辉恒等式:C n m = C n − 1 m + C n − 1 m − 1 C_n^m=C_{n-1}^{m}+C_{n-1}^{m-1}Cnm=Cn1m+Cn1m1

n nn个元素中存在一个元素x xx
如果不选择x xx,那么接下来要在剩下的n − 1 n-1n1个元素中再选择m mm个元素,方案数为C n − 1 m C_{n-1}^{m}Cn1m
如果选择x xx,那么接下来要在剩下的n − 1 n-1n1个元素中再选择m − 1 m-1m1个元素,方案数为C n − 1 m − 1 C_{n-1}^{m-1}Cn1m1
根据加法原理,有C n m = C n − 1 m + C n − 1 m − 1 C_n^m=C_{n-1}^{m}+C_{n-1}^{m-1}Cnm=Cn1m+Cn1m1

C n m = n m C n − 1 m − 1 C_n^m=\dfrac{n}{m}C_{n-1}^{m-1}Cnm=mnCn1m1

C n m = n ! ( n − m ) ! m ! = n m ( n − 1 ) ! ( n − m ) ! ( m − 1 ) ! = n m C n − 1 m − 1 C_n^m=\frac{n!}{(n-m)!m!}=\frac{n}{m}\frac{(n-1)!}{(n-m)!(m-1)!}=\frac{n}{m}C_{n-1}^{m-1}Cnm=(nm)!m!n!=mn(nm)!(m1)!(n1)!=mnCn1m1

2. 二项式定理

( a + b ) n = ∑ i = 0 n C n i a i b n − i (a+b)^n =\sum\limits_{i=0}^nC_n^ia^ib^{n-i}(a+b)n=i=0nCniaibni
或:
( a + b ) n = C n 0 a 0 b n + C n 1 a b n − 1 + . . . + C n n − 1 a n − 1 b + C n n a n b 0 (a+b)^n=C_n^0a^0b^{n}+C_n^1ab^{n-1}+...+C_n^{n-1}a^{n-1}b+C_n^na^nb^{0}(a+b)n=Cn0a0bn+Cn1abn1+...+Cnn1an1b+Cnnanb0

每一个( a + b ) (a+b)(a+b)提供一个a aab bb
对于a i b n − i a^ib^{n-i}aibni项,需要在n nn( a + b ) (a+b)(a+b)中选择i ii( a + b ) (a+b)(a+b)提供a aa,另外n − i n-ini( a + b ) (a+b)(a+b)中提供b bb,共C n i C_n^iCni种情况,根据加法原理,a i b n − i a^ib^{n-i}aibni项的系数为C n i C_n^iCni

【解题思路】

M = 10007 M=10007M=10007,可以手写质数判断函数确定M MM为质数。
已知n + m = k n+m=kn+m=k,所以m = k − n m=k-nm=kn
根据二项式定理,( a x + b y ) k (ax+by)^k(ax+by)kx n y m x^ny^mxnym项为
C k n ( a x ) n ( b y ) k − n = C k n a n b k − n x n y k − n = C k n a n b m x n y m C_k^n(ax)^n(by)^{k-n}=C_k^na^nb^{k-n}x^ny^{k-n}=C_k^na^nb^mx^ny^mCkn(ax)n(by)kn=Cknanbknxnykn=Cknanbmxnym
因此该项的系数为C k n a n b m m o d M C_k^na^nb^m\bmod MCknanbmmodM
可以使用快速幂求a n a^nanb m b^mbm
对于求组合数C k n C_k^nCkn,有以下方法:

1. 求组合数数组
  • 状态定义:设二维数组cc[i][j]表示C i j C_i^jCij。由于k ≤ 1000 k\le 1000k1000,所以数组的行数列数可以定为1005。
  • 初始状态:C i 0 = 1 , i ∈ [ 0 , n ] C_i^0=1, i\in[0,n]Ci0=1,i[0,n],注意包括:C 0 0 = 1 C_0^0=1C00=1
    由于结果要对M MM取模,我们求出的组合数也对M MM取模。
  • 递推关系:C i j ≡ C i − 1 j + C i − 1 j − 1 ( m o d M ) C_i^j\equiv C_{i-1}^{j}+C_{i-1}^{j-1} \pmod MCijCi1j+Ci1j1(modM),其中j ∈ [ 1 , i ] j\in[1,i]j[1,i]

递推求出c数组,即可求出C n k C_n^kCnk
同样可以根据该原理写出记忆化递归算法。
该方法求C n m C_n^mCnm,空间复杂度O ( n 2 ) O(n^2)O(n2),时间复杂度:预处理O ( n 2 ) O(n^2)O(n2),单次查询O ( 1 ) O(1)O(1)

2. 使用阶乘公式

C n m ≡ n ! ( n − m ) ! m ! ( m o d M ) C_n^m\equiv \dfrac{n!}{(n-m)!m!}\pmod MCnm(nm)!m!n!(modM)
设阶乘数组facfac[i]表示i ! i!i!。先预处理出1 ∼ k 1\sim k1k的阶乘。
设阶乘模M MM逆元的数组facInvfacInv[i]表示i ! − 1 m o d M i!^{-1}\bmod Mi!1modM
先使用扩展欧几里得算法求出n ! − 1 m o d M n!^{-1}\bmod Mn!1modM(由于M MM是质数,也可以使用快速幂求逆元)。
已知:i ! − 1 ≡ ( i + 1 ) − 1 ( i + 1 ) ( m o d M ) i!^{-1}\equiv (i+1)^{-1}(i+1)\pmod Mi!1(i+1)1(i+1)(modM)
而后使用该公式递推求出facInv数组。
C n m ≡ n ! ( n − m ) ! m ! ≡ n ! ( n − m ) ! − 1 m ! − 1 ( m o d M ) C_n^m\equiv \dfrac{n!}{(n-m)!m!}\equiv n!(n-m)!^{-1}m!^{-1}\pmod MCnm(nm)!m!n!n!(nm)!1m!1(modM)
fac[n]n ! n!n!facInv[n-1]( n − m ) ! − 1 m o d M (n-m)!^{-1}\bmod M(nm)!1modMfacInv[m]m ! − 1 m o d M m!^{-1}\bmod Mm!1modM,可以通过该公式求出C n m C_n^mCnm

该方法求C n m C_n^mCnm,空间复杂度O ( n ) O(n)O(n),时间复杂度:预处理O ( n ) O(n)O(n),查询O ( 1 ) O(1)O(1).

3. 使用乘除计算公式

C n m ≡ n ( n − 1 ) . . . ( n − m + 1 ) m ( m − 1 ) . . . 1 ( m o d M ) C_n^m\equiv \dfrac{n(n-1)...(n-m+1)}{m(m-1)...1}\pmod MCnmm(m1)...1n(n1)...(nm+1)(modM)
先求出m ! m o d M m!\bmod Mm!modM,再通过扩展欧几里得算法(模数为质数时可用快速幂)求出m ! − 1 m o d M m!^{-1}\bmod Mm!1modM
C n m ≡ n ( n − 1 ) . . . ( n − m + 1 ) m ! − 1 ( m o d M ) C_n^m\equiv n(n-1)...(n-m+1)m!^{-1}\pmod MCnmn(n1)...(nm+1)m!1(modM)
该方法求C n m C_n^mCnm,空间复杂度O ( 1 ) O(1)O(1),时间复杂度:O ( m ) O(m)O(m)

【题解代码】

1. 求组合数数组
  • 写法1:递推
#include<bits/stdc++.h>usingnamespacestd;constintN=1005,M=10007;typedeflonglongLL;LL a,b,k,n,m,c[N][N];//c[i][j]:组合数C(i, j)LLfastPow(LL a,LL b,LL m){LL r=1;while(b>0){if(b%2==1)r=r*a%m;a=a*a%m;b/=2;}returnr;}voidinitComb(LL n){for(inti=0;i<=n;++i)c[i][0]=1;for(inti=1;i<=n;++i)for(intj=1;j<=i;++j)c[i][j]=(c[i-1][j]+c[i-1][j-1])%M;}intmain(){cin>>a>>b>>k>>n>>m;initComb(k);cout<<fastPow(a,n,M)*fastPow(b,m,M)*c[k][n]%M;return0;}
  • 写法2:记忆化递归
#include<bits/stdc++.h>usingnamespacestd;constintN=1005,M=10007;typedeflonglongLL;LL a,b,k,n,m,c[N][N];//c[i][j]:组合数C(i, j)LLfastPow(LL a,LL b,LL m){LL r=1;while(b>0){if(b%2==1)r=r*a%m;a=a*a%m;b/=2;}returnr;}LLcomb(LL n,LL m){if(m>n)return0;if(m==0)return1;if(c[n][m]>0)returnc[n][m];returnc[n][m]=(comb(n-1,m)+comb(n-1,m-1))%M;}intmain(){cin>>a>>b>>k>>n>>m;cout<<fastPow(a,n,M)*fastPow(b,m,M)*comb(k,n)%M;return0;}
2. 使用阶乘公式
#include<bits/stdc++.h>usingnamespacestd;constintN=1005,M=10007;typedeflonglongLL;LL a,b,k,n,m,fac[N],facInv[N];LLfastPow(LL a,LL b,LL m){LL r=1;while(b>0){if(b%2==1)r=r*a%m;a=a*a%m;b/=2;}returnr;}voidinitFac(LL n){fac[0]=1;for(inti=1;i<=n;++i)fac[i]=fac[i-1]*i%M;//fac[i]:i!facInv[n]=fastPow(fac[n],M-2,M);for(inti=n-1;i>=0;--i)//注意包括0facInv[i]=facInv[i+1]*(i+1)%M;//facInv[i]:i!^{-1} mod M}LLcomb(LL n,LL m){if(n<m)return0;returnfac[n]*facInv[n-m]%M*facInv[m]%M;}intmain(){cin>>a>>b>>k>>n>>m;initFac(k);cout<<fastPow(a,n,M)*fastPow(b,m,M)*comb(k,n)%M;return0;}
3. 使用乘除计算公式
#include<bits/stdc++.h>usingnamespacestd;constintN=1005,M=10007;typedeflonglongLL;LL a,b,k,n,m,fac[N],facInv[N];LLfastPow(LL a,LL b,LL m){LL r=1;while(b>0){if(b%2==1)r=r*a%m;a=a*a%m;b/=2;}returnr;}LLcomb(LL n,LL m){if(m>n)return0;LL fz=1,fm=1;for(inti=1;i<=m;++i){fz=fz*(n-i+1)%M;fm=fm*i%M;}returnfz*fastPow(fm,M-2,M)%M;}intmain(){cin>>a>>b>>k>>n>>m;cout<<fastPow(a,n,M)*fastPow(b,m,M)*comb(k,n)%M;return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 10:12:01

场馆预约小程序开发:解锁 “预约经济” 的高效解决方案

在数字化转型加速的背景下&#xff0c;场馆预约需求已渗透体育、办公、教育、文旅等多个领域。传统线下预约模式存在 “信息不透明、操作繁琐、管理低效” 等痛点&#xff0c;而小程序凭借 “轻量化、高触达、易操作” 的优势&#xff0c;成为场馆预约场景的理想载体。本文从核…

作者头像 李华
网站建设 2026/5/27 17:29:01

Product Hunt 每日热榜 | 2025-12-16

1. Unloop 标语&#xff1a;为注意力缺陷多动症&#xff08;ADHD&#xff09;和神经多样性思维者设计的视觉模式映射 介绍&#xff1a;Unloop 是一款可视化的模式映射工具&#xff0c;帮助你识别那些让你感到陷入困境的触发因素、想法、情绪和行为。把这些内容可视化&#xf…

作者头像 李华
网站建设 2026/5/28 0:29:13

软考高项|老金团队三位大神老师,总有一位适合你!

备考软考高项还在为选老师纠结吗&#xff1f; 今天给大家安利老金团队的三大王牌老师 他们各有所长&#xff0c;能cover所有备考需求&#x1f447;&#x1f3c6; 学术泰斗&#xff1a;金老师▪️ 教学特色&#xff1a;30年高校教学经验&#xff0c;理论功底深厚 ▪️ 拿手绝活&…

作者头像 李华
网站建设 2026/5/27 19:36:49

大模型学习笔记

公司私有数据大模型应用方案1. RAG&#xff08;Retrieval Augmented Generation&#xff09;1&#xff09;工作原理RAG 通过从外部知识库中检索相关信息&#xff0c;并将其作为提示输入给大型语言模型&#xff08;LLMs&#xff09;&#xff0c;以增强模型处理知识密集型任务的能…

作者头像 李华
网站建设 2026/5/27 23:41:45

Windows Subsystem for Linux (WSL) 介绍

&#x1f4bb; Windows Subsystem for Linux (WSL) 介绍 WSL&#xff08;适用于 Linux 的 Windows 子系统&#xff09;是微软开发的一项 Windows 功能&#xff0c;它允许开发人员直接在 Windows 操作系统上运行完整的 GNU/Linux 环境&#xff0c;包括大多数命令行工具、实用程序…

作者头像 李华
网站建设 2026/5/28 0:35:32

sward全面介绍(13) - 集成Ldap,使用Ldap用户登录sward

集成ldap用户功能划入社区版本&#xff0c;本篇文章将全面介绍如何在sward中集成ldap用户并实现ldap用户登录sward。1、配置Ldap进入系统设置->用户->用户目录&#xff0c;点击Ldap后的配置按钮&#xff0c;填写Ldap的配置信息。参数说明类型选择Ldap服务器类型AD/LDAP名…

作者头像 李华