组合数求模

0. 写在前面

在程序设计中,可能会碰到多种类型的计数问题,其中不少涉及到组合数的计算,所以笔者写下这么一篇文章,期望能解决一些常规的组合数求模问题。以下部分内容改编自AekdyCoin的《组合数求模》,而且为了感谢他对(懵懂的)笔者的启发,这篇文章的标题与其文章相同。另外,感谢Picks将多项式运算的技巧在中国进行推广,感谢51nod提供了许多有趣的数论题目,感谢fotile96开源了他的FFT模板

在接下来的内容中,文章将围绕C(n,m)modpC(n, m) \bmod p进行分析,其中C(n,m)C(n, m)表示从nn个人中选出mm个人跪sd0061的方案数。

author: skywalkert
original article: http://blog.csdn.net/skywalkert/article/details/52553048
last update time : 2020-03-04

1. 枚举法

这一部分的内容主要是利用基本定义C(n,m)=n!m!(nm)!=n(n1)(nm+1)12mC(n, m) = \frac{n!}{m!(n - m)!} = \frac{n(n - 1)\cdots(n - m + 1)}{1 \cdot 2 \cdots m}来进行分析的。

1.1 直接枚举

如果nm<mn - m < m,不妨将nmn - m视作mm,所以我们只需要考虑mn2m \leq \frac{n}{2}的情况。

1,2,,m1, 2, \cdots, m在模pp意义下有乘法逆元,则考虑直接计算分子、分母在模意义下的值,利用扩展欧几里得算法O(logp)O(\log p)求逆即可,这样做求C(n,m)C(n, m)的复杂度是O(m)O(m)的。注意pp可以不是质数。

如果需要求C(n,1),C(n,2),,C(n,m)C(n, 1), C(n, 2), \cdots, C(n, m),也可以利用上述方法做到O(mlogp)O(m\log p),这是因为C(n,m)=C(n,m1)nm+1mC(n, m) = C(n, m -1) \cdot \frac{n - m + 1}{m}

如果能提前O(m)O(m)预处理1,2,,m1, 2, \cdots, m的逆元,则上述问题可以做到O(m)O(m),这是因为m=xmx+(mmodx)xmx+(mmodx)0(modm)x1mx(mmodx)1(modm)m = x \cdot \left \lfloor \frac{m}{x} \right \rfloor + (m \bmod x) \\ \Rightarrow x \cdot \left \lfloor \frac{m}{x} \right \rfloor + (m \bmod x) \equiv 0 \pmod{m} \\ \Rightarrow x^{-1} \equiv - \left \lfloor \frac{m}{x} \right \rfloor (m \bmod x)^{-1} \pmod{m}

注意,当mm不为质数时,(mmodx)(m \bmod x)不一定与mm互质,所以上述做法需要有mm是质数的条件。

1.2 预处理

由于C(n,m)=n(n1)(nm+1)12m=(n1)(nm+1)12(m1)(1+nmm)=C(n1,m1)+C(n1,m),C(n, m) = \frac{n(n - 1)\cdots(n - m + 1)}{1 \cdot 2 \cdots m} \\= \frac{(n - 1)\cdots(n - m + 1)}{1 \cdot 2 \cdots (m - 1)} (1 + \frac{n - m}{m}) \\= C(n - 1, m - 1) + C(n - 1, m), 所以能够O(nm)O(nm)计算出C(n,m)C(n, m)

注意到上述式子只涉及加法,所以不需要考虑是否有逆元的问题。

这种做法可以预先处理出一定范围内的所有组合数,将计算多个组合数转化为查表,适用于多次查询组合数的问题。

1,2,,n1, 2, \cdots, n在模pp意义下有乘法逆元,也可以预处理n!n!(n!)1(n!)^{-1},当逆元可以线性预处理时(pp为质数),阶乘和阶乘的逆元也可以O(n)O(n)预处理。

注意,当nn远大于mm时,或许直接枚举的做法会更好。

1.3 质因数分解

1,2,,m1, 2, \cdots, m中存在数字在模pp意义下没有逆元,则需要避免使用相应的除法,而是在运算前将分子和分母中的相关项相消,一个显而易见的想法便是将分子和分母所对应的阶乘化为质因数分解式,在质因数的幂次上进行加减法。计算一个数的幂可以利用快速模幂算法做到幂次的对数复杂度。

如果不考虑模pp意义,则只需要考虑分母中所含的质因数,分子也只需要对这些质因数进行分解,其他剩余的部分可以当作整体,这样做是O(mlogm)O(m \log m)的,可在分母超出存储范围但是精确值不超过存储范围时使用。

而考虑模pp意义,则注意到需要消除的数都是与pp的最大公约数大于1的,因此只需要考虑pp的质因数,将与pp互质的部分直接计算(互质的分母部分直接求逆元),不互质的部分维护成质因数的幂次即可,这样做是O(mlogp)O(m \log p)的,与1.1同理可以求C(n,1),C(n,2),,C(n,m)C(n, 1), C(n, 2), \cdots, C(n, m)

nnmm同阶时,可以利用线性的筛法维护一些额外信息,从而O(n)O(n)完成组合数的质因数分解。具体做法如下:

  1. 用筛法计算出正整数x (xn)x\ (x \leq n)的一个质因数prx{pr}_x
  2. 维护一个数组c1,c2,,cnc_1, c_2, \cdots, c_n使得C(n,m)=i=1niciC(n, m) = \prod_{i = 1}^{n}{i^{c_i}},初始化每个位置为0,然后使c1,c2,,cnc_1, c_2, \cdots, c_n各加一,c1,c2,,cmc_1, c_2, \cdots, c_m各减一,c1,c2,,cnmc_1, c_2, \cdots, c_{n - m}各减一。
  3. 降序枚举x (2xn)x\ (2 \leq x \leq n),如果xx不为质数,则将xcxx^{c_x}拆分为prxcx(xprx)cx{{pr}_x}^{c_x}\cdot (\frac{x}{{pr}_x})^{c_x},具体操作是修改cx,cprx,cxprxc_x, c_{{pr}_x}, c_{\frac{x}{{pr}_x}}
  4. 此时cxc_x不为0则必然xx为质数,而且xx为质数时cxc_x非负,即为组合数的质因数分解。

当然,如果只有少量数字没有逆元,还可以考虑扩大模数。例如,只有xx没有逆元,但是要除以一个xx,则可以计算原式在模xpx\cdot p意义下的值,再除以xx,而如果有多个数字时,也可将模数扩大它们的乘积倍。但一般情况下,这种方法的效率不高。

2. 定理法

这一部分的内容将涉及初等数论中两个常用的定理,利用定理将复杂的问题简单化,从而便于分析。

2.1 卢卡斯定理 (Lucas’ theorem)

在数论中,卢卡斯定理将组合数C(n,m)C(n, m)在模质数pp意义下的值表示成一系列组合数C(ni,mi)C(n_i, m_i)的乘积,其中ni,min_i, m_i分别表示n,mn, mpp进制下的第ii位数字,换句话说,令n=i=0knipi,m=i=0kmipin = \sum_{i = 0}^{k}{n_i \cdot p^i}, m = \sum_{i = 0}^{k}{m_i \cdot p^i},则有C(n,m)i=0kC(ni,mi)(modp)C(n, m) \equiv \prod_{i = 0}^{k}{C(n_i, m_i)} \pmod{p}

其中,如果ni<min_i < m_iC(ni,mi)=0C(n_i, m_i) = 0。另外,这个定理的证明还用到了一个常用于化简式子的公式:当pp是质数时,(A+B)pAp+Bp(modp)(A + B)^p \equiv A^p + B^p \pmod{p}

nn远大于pp时,利用卢卡斯定理,我们可以将组合数化简到小于pp的情况,从而在套用1.2中的预处理阶乘和阶乘逆元时,复杂度从O(n)O(n)降到了O(p)O(p)

假设能够轻松地(进制转换)得到pp进制下的n,mn, m,则只需要计算O(k)=O(logn)O(k)=O(\log n)个组合数,所以复杂度是O(p+logn)O(p + \log n)。但是希望大家能注意到卢卡斯定理的局限性:它只适用于模质数的情况。

2.2 中国剩余定理 (Chinese Remainder Theorem)

中国剩余定理适用于化简模线性方程组,具体来说,如果有{xr1(modm1)xr2(modm2)xrk(modmk)\begin{cases} x \equiv r_1 \pmod{m_1} \\ x \equiv r_2 \pmod{m_2} \\ \cdots \\ x \equiv r_k \pmod{m_k} \end{cases},其中gcd(mi,mj)=1 (ij)\gcd(m_i, m_j) = 1\ (i \neq j),那么利用中国剩余定理可以得到xi=1kriMiMi(modM)x \equiv \sum_{i = 1}^{k}{r_i M'_i M_i \pmod{M}}与原方程组等价,其中M=i=1kmi,Mi=MmiM = \prod_{i = 1}^{k}{m_i}, M_i = \frac{M}{m_i},而MiMi1(modmi)M'_i \equiv {M_i}^{-1} \pmod{m_i}

中国剩余定理实际上利用kk次求逆元将方程组进行了合并,而一般情况下可能出现方程组模数不互质的情况,有两种解决办法。一种是将模数分解质因数,划分成多个小的方程组,同质数的方程组再根据幂次判断合法性并合并。另一种是利用二元一次不定方程的通解判断合法性和合并方程组。一般来说,前者需要增加代码量,后者需要一定的推导。

利用中国剩余定理,我们可以将模pp的问题转化为模其质因子幂次的问题。当ppsquare-free number(因子中的平方数只有 1)时,可以结合卢卡斯定理分别解决问题,再将结果合并。当pp不是square-free number时,需要使用下文的一些方法。

3. 其他化归法

这一部分的内容将涉及笔者认为常用的其他化简、归纳方法。笔者不才,私以为将这些方法与前面的结论相结合,可以解决目前大部分组合数求模的问题。

3.1 阶乘表示法

与1.3类似,在这一节我们考虑将组合数表示成pp的质因数的幂次和其他部分,尝试简化问题,但不同的是,由于中国剩余定理的支持,这一节我们只考虑pp是质因数幂次的情况,即p=qep=q^e

组合数可以表示成阶乘和阶乘逆元的乘积,所以我们只要考虑如何表示阶乘。设n!=qknvnn! = q^{k_n} \cdot v_n,其中vnv_nqq互质,则需要计算knk_n的精确值与vnmodqev_n \bmod q^e

阶乘n!n!可以表示成前nn个连续正整数1,2,,n1, 2, \cdots, n的乘积,将这nn个数中与qq互质的数提取出来,这一部分的数乘积累积给vnv_n。而不互质的数必然是q,2q,,nqqq, 2 \cdot q, \cdots, \left \lfloor \frac{n}{q} \right \rfloor \cdot q,每个数字提取一个qq,则至少可以提取出nq\left \lfloor \frac{n}{q} \right \rfloorqq累加给knk_n。那么剩下没考虑的数字就是1,2,,nq1, 2, \cdots, \left \lfloor \frac{n}{q} \right \rfloor,也即nq!\left \lfloor \frac{n}{q} \right \rfloor!,再次重复上述过程进行提取即可。

提取qq的过程是十分简单的,只需要O(logn)O(\log n)次提取。而主要的复杂度在于计算1,2,,n1, 2, \cdots, n中与qq互质的数字乘积在模qeq^e意义下的取值。由于1,2,,qe1, 2, \cdots, q^eqe+1,qe+2,,2qeq^e + 1, q^e + 2, \cdots, 2\cdot q^e在模意义下对应相等,因此可以将1,2,,n1, 2, \cdots, n表示成nqe\left \lfloor \frac{n}{q^e} \right \rfloor1,2,,qe1, 2, \cdots, q^e1,2,,nmodqe1, 2, \cdots, n \bmod q^e,因此可以预处理前x (x<qe)x\ (x < q^e)个正整数里与qq互质的数字乘积,再利用快速模幂算法高斯泛化的威尔逊定理处理前者,这样做的整体复杂度是O(qe+logn)O(q^e + \log n)。这个做法在e=1e = 1时等同于2.1中的预处理。

3.2 分治与多项式

继续分析上一节中的互质的数字乘积问题,在上一节中我们只用到了模qeq^e的循环节,但是在这样的循环节中还是有qe1q^{e - 1}个位置是不产生贡献的,剩下产生贡献的位置被分成了许多个长度为q1q - 1的区间,当e>1e > 1时是十分浪费的。

考虑多项式f(x)=(x+1)(x+2)(x+q1)f(x)=(x+1)(x+2)\cdots(x+q - 1)f(0)f(0)就表示了区间[1,q)[1, q)中正整数的乘积,f(q)f(q)就表示了[q+1,2q)[q+1,2\cdot q)的情况,以此类推我们可以表示出循环节中每个长度为q1q - 1的区间乘积,而前n (n<qe)n\ (n < q^e)个正整数里与qq互质的数字乘积就可以表示为多项式在前nq\left \lfloor \frac{n}{q} \right \rfloorqq的非负倍数处的取值乘积,再乘上不超过qq个零碎的数字,问题再一次化简。

注意到xx的取值是qq的倍数时,这个多项式里xix^i的项的取值一定是qiq^i的倍数,故当iei \geq exix^i的项在模意义下一定为00,因此多项式可以在模xex^e意义下进行运算。(更高效而且更优美的性质是,多项式里 xix^i 的系数只需要在模 qeiq^{e - i} 意义下维护即可)

考虑这样一个事实:如果已知[x+1,x+aq)[x+1,x+aq)对应的多项式为g(x)g(x),则[x+1,x+2aq)[x+1,x+2aq)对应的多项式为g(x)g(x+aq)g(x)\cdot g(x + aq)。同理可以用[x+1,x+aq)[x+1, x+aq)[x+1,x+bq)[x+1, x+bq)的结果得到[x+1,x+(a+b)q)[x+1, x+(a+b)q)的结果。而我们的运算都是在前ee项进行的,因此利用类似快速幂的方法可以得到[x+1,x+nqq)[x+1, x+\left \lfloor \frac{n}{q} \right \rfloor q)对应的多项式,再求其常数项(即f(0)f(0))与零碎的数字乘积的值即可,这样做是O((q+e3)logn)O((q+e^3) \log n)的,如果将 O(e)O(e) 次计算的顺序调整一下,复杂度可以做到 O((q+e2)logn)O((q + e^2) \log n) ,并且不会使用到高斯泛化的威尔逊定理。

qe2>1q \geq e^2 > 1时,q=p1e=O(p)q = p^{\frac{1}{e}} = O(\sqrt{p}),总复杂度也可以写为O(plogn)O(\sqrt{p} \log n),可以完成一些相对来说比较大的情况。

3.3 分块与多项式

还是继续分析上一节中的互质的数字乘积问题,在上一节中我们对e>1e > 1的情况取得了较好的做法,在这一节中我们会对e=1e = 1的情况进行另外一个方向的分析,即组合数模大质数问题。

我们需要考虑的是计算n! (n<p)n!\ (n < p)在模质数pp意义下的值,直接求值会很慢,但直接构建多项式会使得构建过慢、求值很快。为了均衡二者,可以设定一个阈值TT,构建多项式Q(x)=i=1T(x+i)Q(x) = \prod_{i = 1}^{T}{(x + i)},尝试求出Q(0),Q(1),,Q(nT+1T)Q(0), Q(1), \cdots, Q(\left \lfloor \frac{n - T + 1}{T} \right \rfloor),与剩下不超过TT个零碎的数字直接乘起来,从而得到n!n!

多项式Q(x)Q(x)是一个次数为TT的多项式,利用分治+FFT构建这个多项式的复杂度是O(Tlog2T)O(T \log^2 T)。由于多项式Q(x)Q(x)在一个点x=xix = x_i的取值即Q(x)mod(xxi)Q(x) \bmod (x - x_i),因此在多点求值可以利用分治的技巧,将求值的序列一分为二,同时将多项式降次成两个次数更小的多项式,这其中需要预处理构建一些辅助多项式,从而做到复杂度为O(nTlog2nT)O(\frac{n}{T} \log^2 \frac{n}{T})。综上所述,TT的最优值应取O(n)O(\sqrt{n}),限于常数问题可能需要自行调参,总体的复杂度为O(nlog2n)O(\sqrt{n} \log^2 n)

在上述过程中涉及到的系数运算都是模pp意义下的,但直接使用FFT会使得过程中数值达到O((Tp)2)O((Tp)^2)的级别,利用修正许多误差且使用优化技巧的FFT可以将数值降到O(T2p)O(T^2 p)级别。

3.4 更复杂的情况

如果对扩展Lucas定理感兴趣,可以参考Andrew Granville在1997年发表的文章Arithmetic Properties of Binomial Coefficients I: Binomial coefficients modulo prime powers,适合 e>1e > 1 的情况。但是笔者从论文中了解到的做法比3.2的做法要差一点,做法类似于拉格朗日插值法求出互质的数字乘积,而3.2中维护多项式的做法会更加灵活、高效。

可以发现,当e>1e > 1时3.2的做法比3.3的做法更好,但也不难发现,3.3中提到的分块技巧是可以与3.2中的分治技巧进行结合的(弥补其中 O(q)O(q) 的部分),如果对于更加一般化的做法感兴趣,欢迎与我联系。

4. 例题讲解

这一部分的内容将按照上文内容的顺序依次讲解适用相关方法的例题,目的是加深对相关方法的理解与应用。

4.1 Ural 1114 Boxes

简要题意

nn个盒子、aa个红球和bb个蓝球,每个盒子可以放任意多个红球和任意多个蓝球,盒子可以空着,球也可以不全放进去,问有多少种放求的方案数。

1n20,0a,b151 \leq n \leq 20, 0 \leq a, b \leq 15

简要题解

红蓝球互不影响,分别计算方案数后相乘即可。而mm个球放到nn个盒子的方案数即C(m+n1,n1)C(m+n-1,n-1),假设多一个盒子放置那些没放进去的球,则可知方案数为C(m+n,n)C(m+n,n),即答案为C(a+n,n)C(b+n,n)C(a+n, n)\cdot C(b + n, n)。初步估算最大值为C(35,20)21019C(35, 20)^2 \approx 10^{19},因此需要使用64位无符号整型数存储,~~为了不使运算过程中出现溢出,需要使用质因数分解的方法,~~套用1.2使用加法预处理组合数即可。

4.2 UVaLive 7040 color

简要题意

nn个连续的格子和mm种不同颜色的染料,现在要用恰好kk种染料对这nn个格子染色,每种染料至少染一个格子,并且任意相邻的格子颜色不同,问这样选出染料并染色的合法方案数对109+710^9+7取模的值。

1n,m109,1kmin(106,n,m)1 \leq n, m \leq 10^9, 1 \leq k \leq \min(10^6, n, m)

简要题解

选出kk种颜色的方案是C(m,k)C(m, k),最后乘上即可。如果只是使得任意相邻的格子颜色不同,那么方案数是k(k1)n1k \cdot (k - 1)^{n - 1}。现在要使得每种染料至少染一个格子,则可以考虑上述方案中只出现i(ik)i(i \leq k)个颜色的方案f(i)f(i),则有k(k1)n1=ikC(k,i)f(i)k \cdot (k - 1)^{n - 1} = \sum_{i \leq k} C(k, i) \cdot f(i),利用二项式反演可以得到f(k)=ik(1)kiC(k,i)i(i1)n1f(k) = \sum_{i \leq k} {(-1)^{k - i} C(k, i) \cdot i \cdot (i - 1)^{n - 1}}。因此只需要预处理逆元后直接枚举C(k,i)C(k, i)即可,时间复杂度O(k+klnklogn)O(k + \frac{k}{\ln k}\log n)

4.3 COGS 1284 [HNOI2004] 树的计数

简要题意

已知一个有nn个结点的树第ii个结点的度数为did_i,问满足这样的条件的不同的树有多少棵。

n150n \leq 150,保证答案不超过101810^{18}

简要题解

由树的Prüfer序列可知,第ii个结点会在序列中出现di1d_i - 1次,总共有n2n - 2个数字,所以答案为(n2)!i=1n(di1)!\frac{(n - 2)!}{\prod_{i = 1}^{n}{(d_i - 1)!}},由于保证了答案不超过101810^{18},保险起见最好将式子表示成一些数字的乘积,因此需要套用1.3中的质因数分解方法。

4.4 BNUOJ 51637 Quailty’s Life

简要题意

(0,0)(0, 0)出发走到x=nx = ny=my = m,每一步需要使横坐标或纵坐标加一,也可使二者同时加一,路上不能走到kk个定点(ai,bi) (i=1,2,,k)(a_i, b_i)\ (i = 1, 2, \cdots, k),问路径的方案数对pp取模的值。

1n109,1m104,0k10,1p<2311 \leq n \leq 10^9, 1 \leq m \leq 10^4, 0 \leq k \leq 10, 1 \leq p < 2^{31}

简要题解

详细题解见BNUOJ 51637 Quailty’s Life | BZOJ 4587 推箱子

首先对于kk个定点进行去重,不难发现一个定点能到达另一个定点这样的关系构成一个有向无环图,因此可以尝试进行容斥,设f(i)f(i)表示从起点出发走到第ii个定点且之前没有走到其他定点的方案数,way(x,y)\text{way}(x, y)表示横坐标增加xx、纵坐标增加yy的路径方案数,则有f(i)=way(ai,bi)jif(j)way(aiaj,bibj)f(i) = \text{way}(a_i, b_i) - \sum_{j \neq i}{f(j) \cdot \text{way}(a_i - a_j, b_i - b_j)},这只需要O(k2)O(k^2)次计算way(x,y)\text{way}(x, y)

问题在于计算way(i,j)\text{way}(i, j),而且对于最后的终止情况还需要计算i=ni=nj=mj=m的情况之和。设从(0,0)(0,0)走到(i,j)(i,j)的一种方案使用了aax+1x+1bby+1y+1ccx+1x+1同时y+1y+1,则有
{a+c=ib+c=ja,b,c0{a=icb=jc0cmin(i,j)\begin{cases}a+c=i\\b+c=j\\a,b,c\geq0\end{cases}\Rightarrow\begin{cases}a=i-c\\b=j-c\\0\leq c\leq\min(i,j)\end{cases},对应的方案数是(i+jc)!(ic)!(jc)!c!=C(i+jc,i)C(i,c)=C(j+ic,j)C(j,c)\frac{(i+j-c)!}{(i-c)!(j-c)!c!}=C(i+j-c,i) \cdot C(i,c)=C(j+i-c,j) \cdot C(j,c)。对于最后的求和部分,先考虑i=ni=n的情况,则0jm0\leq j\leq m的情况为j=0mc=0min(n,j)C(n+jc,n)C(n,c)=c=0min(n,m)C(n,c)j=cmC(n+jc,n)=c=0min(n,m)C(n,c)C(n+1c,n+1),\sum_{j=0}^{m}\sum_{c=0}^{\min(n,j)}{C(n+j-c,n) \cdot C(n,c)}=\sum_{c=0}^{\min(n,m)}{C(n,c)\sum_{j=c}^{m}{C(n+j-c,n)}}=\sum_{c=0}^{\min(n,m)}{C(n,c) \cdot C(n+1-c,n+1)}, 那么也是枚举cc就可以了,不用枚举jj。对于0in,j=m0\leq i\leq n, j=m的情况也这么分析一下。不过因为(n,i)(n,i)走不到(n,i+1)(n,i+1),所以这个题不是求无阻碍到i=ni = nj=mj = m的方案数,但是到终止状态前的一个点是无阻碍的,枚举前一个点算贡献即可。

而计算C(n,0),C(n,1),,C(n,c),(modp)C(n, 0), C(n, 1), \cdots, C(n, c), \cdots \pmod{p}可以套用1.3中的做法做到O(mlogp)O(m\log p)的,整体复杂度O(k2mlogp)O(k^2 m \log p)

4.5 POJ 2992 Divisors

简要题意

C(n,m)C(n, m)的约数个数。

0mn4310 \leq m \leq n \leq 431,保证答案不超过(2631)(2^{63}-1)

简要题解

利用1.3中的线性筛法将C(n,m)C(n, m)表示成质数的幂次即可,答案即x is prime(cx+1)\prod_{x\text{ is prime}}{(c_x + 1)},时间复杂度O(n)O(n)

4.6 ZOJ 2116 Christopher

简要题意

给定正整数nn和质数pp,求m=0,1,,nm = 0, 1, \cdots, n中满足C(n,m)C(n, m)pp的倍数的mm个数。

1n10100,1p1071 \leq n \leq 10^{100}, 1 \leq p \leq 10^7

简要题解

nnpp进制按2.1的方式表示出来,可以发现C(n,m)≢0(modp)C(n, m) \not \equiv 0 \pmod{p},则每一位都有0mini0 \leq m_i \leq n_i,所以不满足条件的数字个数为i=0k(ni+1)\prod_{i = 0}^{k}{(n_i+1)},答案为(n+1)i=0k(ni+1)(n + 1) - \prod_{i = 0}^{k}{(n_i+1)}

4.7 HDU 5446 Unknown Treasure

简要题意

给出n,m,k,p1,p2,,pkn, m, k, p_1, p_2, \cdots, p_k,保证p1,p2,,pkp_1, p_2, \cdots, p_k是两两不同的质数,令P=i=1kpiP = \prod_{i = 1}^{k}{p_i},求C(n,m)modPC(n, m) \bmod P

1mn1018,1k10,1p1,p2,,pk105,1P10181 \leq m \leq n \leq 10^{18}, 1 \leq k \leq 10, 1 \leq p_1, p_2, \cdots, p_k \leq 10^5, 1 \leq P \leq 10^{18}

简要题解

恰好符合2.2中的限定,只需要对于每个质数利用卢卡斯定理求组合数,最后再利用中国剩余定理合并即可。

4.8 CDOJ 1177 pow(a, C(n,m) ) % k

简要题意

给出a,n,m,ka, n, m, k,求aC(n,m)modka^{C(n, m)} \bmod k

1a1018,0n,m1018,1k1051 \leq a \leq 10^{18}, 0 \leq n, m \leq 10^{18}, 1 \leq k \leq 10^5

简要题解

考虑a0,a1,,aka^0, a^1, \cdots, a^k在模kk意义下必然存在两个相同的数字,因此可以计算出幂次的循环节L (Lk)L\ (L \leq k)(实际上Lφ(k)L \mid \varphi(k)),而LL可以枚举得出,所以问题可以转化为C(n,m)modLC(n, m) \bmod L,由于LL不一定是square-free number,所以需要使用3.1中阶乘表示的方法。注意可能存在a0,a1,,at(modk)a^0, a^1, \cdots, a^t \pmod{k}不属于循环节,在 mnmm \leq n -m 时可以根据 mm 的大小来确定 C(n,m)<LC(n, m) < Lnn 范围,如果 nn 真的足够小,那么可以计算实际值,否则直接计算模意义下的组合数即可。

4.9 BZOJ 4535 [Ontak2013]Kapita加强版

简要题意

给出n,m,en, m, e,求C(n+m,n)C(n+m, n)去掉所有末尾的 0 后对10e{10}^e取模的值。

1n,m1015,1e181 \leq n, m \leq 10^{15}, 1 \leq e \leq 18

简要题解

C(n+m,m)C(n+m,m)的末尾有tt个 0 ,而且C(n+m,m)=2k1v1=5k2v2C(n+m,m)=2^{k_1}\cdot v_1=5^{k_2}\cdot v_2,其中v1v_1与 2 互质,v2v_2与 5 互质。显然t=min(k1,k2)t=\min(k_1,k_2),因此C(n+m,m)10t=2k1tv15t=5k2tv22t\frac{C(n+m,m)}{10^t}=2^{k_1-t}\cdot\frac{v_1}{5^t}=5^{k_2-t}\cdot\frac{v_2}{2^t}。只要能算出k1,v1mod2e,k2,v2mod5ek_1,v_1 \bmod 2^e,k_2,v_2 \bmod 5^e,就可以利用中国剩余定理得到答案了, 为了算出这四个数,只需要套用3.2的做法。

4.10 51nod 1387 移数字

简要题意

对于长度为n (n3)n\ (n \geq 3)的排列定义一种操作是将第 3 个元素或最后一个元素移到排列的开头。问有多少种长度为nn的排列能使用这种操作将其变成1,2,,n1, 2, \cdots, n,答案对质数pp取模。

3n109,p=a2b+12109 (a,bZ,a>0,b16)3 \leq n \leq 10^9, p = a \cdot 2^b + 1 \leq 2 \cdot 10^9\ (a, b \in \mathbb{Z},a > 0, b \geq 16)

简要题解

考虑操作对排列逆序对数奇偶性的变化,第一种操作的变化是偶数,第二种操作的变化与nn的奇偶性相反,因而当nn为偶数时答案为n!n!,当nn为奇数时答案为n!2\frac{n!}{2}。而算阶乘的部分只需要套用3.3的做法,注意到p=a2b+1 (b16)p = a \cdot 2^b + 1\ (b \geq 16),所以FFT的复根可以利用原根的幂次来替代,从而消除误差,因此也不需要使用改良版的FFT,这里的原根是指满足gp11(modp)g^{p-1}\equiv 1\pmod{p}且对于任意d>1,dp1d>1,d | p-1gp1d≢1(modp)g^\frac{p-1}{d}\not \equiv 1\pmod{p}的元素gg,具体的替代方法不再赘述。


组合数求模的技巧暂时告一段落

©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值