组合数取模的几个方法

求:

\[C^{m}_{n} \bmod P
\]

1.杨辉三角法

\[C^{m}_{n} = C^{m - 1}_{n - 1} + C^{ m }_{n - 1}
\]

时间复杂度有点小高

2.若 \(n\) 比较大,但 \(P\) 比较小

使用 \(EXlucas\) 大法.

具体讲解点这里:戳我

3.若 \(n\) 比较小, \(P\) 炒几大

我们考虑分解组合数:

原式为:

\[\frac{n!}{\left(n - m\right)! \times m! }
\]

化简为:

\[\frac{\prod_{i = m + 1}^{n}i}{\prod^{n - m}_{i=1}i}
\]

考虑对每一个 \(i\) 分解质因数,但由于全分解的时间复杂度忒高,于是先将其最小的分出来。

开一个长度为 \(n\) 的 \(cnt\) 数组 \(cnt_i\) 表示 \(i\) 的 \(cnt_i\) 次幂。

从大往小里枚举,只要其不是质数,就考虑如下转化:


cnt[i / num[i]] += cnt[i]; cnt[num[i]] += cnt[i];

易证其正确性。

下面一道例题: ( \(Catlan\) )

\(HNOI2009\) 有趣的数列

我们称一个长度为 \(2n\) 的数列是有趣的,当且仅当该数列满足以下三个条件:

  • 它是从 \(1 \sim 2n\) 共 \(2n\) 个整数的一个排列 \(\{a_n\}_{n=1}^{2n}\);

  • 所有的奇数项满足 \(a_1<a_3< \dots < a_{2n-1}\),所有的偶数项满足 \(a_2<a_4< \dots <a_{2n}\);

  • 任意相邻的两项 \(a_{2i-1}\) 与 \(a_{2i}\) 满足:\(a_{2i-1}<a_{2i}\)。

对于给定的 \(n\),请求出有多少个不同的长度为 \(2n\) 的有趣的数列。

因为最后的答案可能很大,所以只要求输出答案对 \(p\) 取模。

输入格式

一行两个正整数 \(n,p\)

输出格式

输出一行一个整数表示答案。

样例输入

3 10

样例输出

5

数据范围

对于 \(50\%\) 的数据,\(1\le n \le 1000\);

对于 \(100\%\) 的数据,\(1\le n \le 10^6\),\(1\le p \le 10^9\)。

\(code\)

简化题意,求:

\[\frac{C^{n}_{2n}}{n + 1}
\]

易推出是卡特兰数,代码如下:

114514
#include<bits/stdc++.h>
using namespace std ;
#define int long long
const int N = 1000010 ;
int n , mod ;
int num , prime[ 2 * N ] ;
int Next[ N << 1 ] ;
int cnt[ N << 1 ] ;
inline int read( )
{
int x = 0 , f = 1 ;
char c = getchar( ) ;
while ( c > '9' || c < '0' )
{
if( c == '-' )
{
f = -f ;
}
c = getchar( ) ;
}
while ( c >= '0' && c <= '9' )
{
x = x * 10 + c - '0' ;
c = getchar( ) ;
}
return x * f ;
}
inline int Regular_Quick_Pow( int a , int b )
{
int ans = 1 ;
while ( b > 0 )
{
if ( b & 1 ) ans = ( ans * a ) % mod ;
b >>= 1 ;
a = ( a * a ) % mod ;
}
return ans ;
}
signed main( )
{
#ifndef ONLINE_JUDGE
freopen( "1.in" , "r" , stdin ) ;
freopen( "1.out" , "w" , stdout ) ;
#endif
cin >> n >> mod ;
for ( int i = 2 ; i <= 2 * n ; ++ i )
{
if ( !Next[ i ] )
{
Next[ i ] = i ;
prime[ ++ num ] = i ;
}
for ( int j = 1 ; j <= num && prime[ j ] * i <= 2 * n ; ++ j )
{
Next[ prime[ j ] * i ] = min( prime[ j ] , Next[ i ] ) ;
}
}
Next[ 1 ] = 1 ;
for ( int i = n + 2 ; i <= 2 * n ; ++ i )
{
cnt[ i ] = 1 ;
}
for ( int i = 1 ; i <= n ; ++ i )
{
cnt[ i ] = -1 ;
}
for ( int i = 2 * n ; i >= 1 ; -- i )
{
if ( Next[ i ] != i )
{
cnt[ Next[ i ] ] += cnt[ i ] ;
cnt[ i / Next[ i ] ] += cnt[ i ] ;
cnt[ i ] = 0 ;
}
}
int ans = 1 ;
for ( int i = 1 ; i <= 2 * n ; ++ i )
{
ans = ( ans * Regular_Quick_Pow( i , cnt[ i ] ) ) % mod ;
}
cout << ans ;
}

组合数取模的几种方法--Exlucas&杨辉三角&组合的更多相关文章

  1. Java小题,通过JNI调用本地C++共享库中的对应方法实现杨辉三角的绘制

    1.在Eclipse中配置Javah,配置如下 位置是你javah.exe在你电脑磁盘上的路径 位置:C:\Program Files\Java\jdk1.8.0_112\bin\javah.exe ...

  2. Python练习题——用列表的方法输出杨辉三角

    def main(): num = int(input('请输入行数: ')) yh = [[]] * num #创建num行空列表 for row in range(len(yh)): #遍历每一行 ...

  3. java实现组合数_n!_杨辉三角_组合数递推公式_回文数_汉诺塔问题

    一,使用计算机计算组合数 1,设计思想 (1)使用组合数公式利用n!来计算Cn^k=n!/k!(n-k)!用递推计算阶乘 (2)使用递推的方法用杨辉三角计算Cn+1^k=Cn^k-1+Cn^k 通过数 ...

  4. 组合数取模Lucas定理及快速幂取模

    组合数取模就是求的值,根据,和的取值范围不同,采取的方法也不一样. 下面,我们来看常见的两种取值情况(m.n在64位整数型范围内) (1)  , 此时较简单,在O(n2)可承受的情况下组合数的计算可以 ...

  5. [BZOJ 3129] [Sdoi2013] 方程 【容斥+组合数取模+中国剩余定理】

    题目链接:BZOJ - 3129 题目分析 使用隔板法的思想,如果没有任何限制条件,那么方案数就是 C(m - 1, n - 1). 如果有一个限制条件是 xi >= Ai ,那么我们就可以将 ...

  6. BZOJ_2142_礼物_扩展lucas+组合数取模+CRT

    BZOJ_2142_礼物_扩展lucas+组合数取模 Description 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E 心目中的重要性不同 ...

  7. 组合数取模&&Lucas定理题集

    题集链接: https://cn.vjudge.net/contest/231988 解题之前请先了解组合数取模和Lucas定理 A : FZU-2020  输出组合数C(n, m) mod p (1 ...

  8. HDU 5698 大组合数取模(逆元)

    瞬间移动 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submis ...

  9. Uva12034 (组合数取模)

    题意:两匹马比赛有三种比赛结果,n匹马比赛的所有可能结果总数 解法: 设答案是f[n],则假设第一名有i个人,有C(n,i)种可能,接下来还有f(n-i)种可能性,因此答案为 ΣC(n,i)f(n-i ...

  10. 组合数取模及Lucas定理

    引入: 组合数C(m,n)表示在m个不同的元素中取出n个元素(不要求有序),产生的方案数.定义式:C(m,n)=m!/(n!*(m-n)!)(并不会使用LaTex QAQ). 根据题目中对组合数的需要 ...

随机推荐

  1. Linux 内核:利用of_函数读取设备树结点/属性信息

    Linux 内核:利用of_函数读取设备树结点/属性信息 背景 设备树描述了设备的详细信息,这些信息包括数字类型的.字符串类型的.数组类型的,我们在编写驱动的时候需要获取到这些信息. Linux 内核 ...

  2. UEFI与inf文件

    UEFI与inf文件 背景 学习高通UEFI中的LCD显示框架,看到有些博客对inf文件进行了介绍,因此整理了这方面的一些入门知识. 参考: https://blog.csdn.net/yunfeng ...

  3. 可重入锁思想,设计MQ迁移方案

    如果你的MQ消息要从Kafka切换到RocketMQ且不停机,怎么做?在让这个MQ消息调用第三方发奖接口,但无幂等字段又怎么处理?今天小傅哥就给大家分享一个关于MQ消息在这样的场景中的处理手段. 这是 ...

  4. 透视开源生态,OSGraph——GitHub全域数据图谱的智能洞察工具

    "透视开源生态,OSGraph--GitHub全域数据图谱的智能洞察工具 OSGraph (Open Source Graph) 是一个开源图谱关系洞察工具,基于GitHub开源数据全域图谱 ...

  5. 全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与“file-like object“

    全网最适合入门的面向对象编程教程:17 类和对象的 Python 实现-鸭子类型与"file-like object" 摘要: 本文主要介绍了 Python 中创建自定义类时鸭子类 ...

  6. git 怎么将某个开发分支最近几次的提交合并成一次提交

    1. 切换到开发分支: git checkout dev 2. 运行交互式 rebase 命令,并指定要合并的提交数量(在这个例子中是最近的3次提交): git rebase -i HEAD~3 3. ...

  7. [oeasy]python019_ 如何在github仓库中进入目录_找到程序代码_找到代码

    继续运行 回忆上次内容 上上次 真写了万行代码 这 万行代码 都是写在明面上的 这次 使用git命令 下载了 github上面的仓库       添加图片注释,不超过 140 字(可选)   下载仓库 ...

  8. WebAPI规范设计——违RESTful

    本文首先简单介绍了几种API设计风格(RPC.REST.GraphQL),然后根据实现项目经验提出WebAPI规范设计思路,一些地方明显违反了RESTful风格,供大家参考! 一.几种设计风格介绍 1 ...

  9. Excel快速下拉填充序列至10000行

    问题:想要下拉输入的数据递增得到1.2.3--10000,但是手动下拉太累 解决: 1.如在A1单元格输入1,在A2单元格输入2 2.选中A2单元格,在上方名称框中填写A2:A1000,回车,此时将选 ...

  10. pytest批量执行多个测试文件(批量执行一个文件夹下的所有测试用例)

    图片 代码 #!/usr/bin/env python # @File : test_runall.py import pytest import os # path = os.path.dirnam ...