数论篇7——组合数 & 卢卡斯定理(Lucas)
组合数
组合数就是高中排列组合的知识,求解组合数C(n,m),即从n个相同物品中取出m个的方案数。
求解方式
求解通式:$C^{m}_{n}=\dfrac {n!}{m!\left( n-m\right) !}$
性质1:$C^{m}_{n}=C_{n}^{n-m}$
性质2:$C^{m}_{n}=C^{m-1}_{n-1}-i+C^{m}_{n-1}$
打表递推
根据性质2:$C^{m}_{n}=C^{m-1}_{n-1}+C^{m}_{n-1}$
组合数算出来特别大,往往都会要求取余,这里取$P=1e9+7$。时间复杂度$O(n^2)$
; #define N 1000 int comb[N][N]; int main() { ; i < N; i++) { comb[i][] = comb[i][i] = ; ; j < i; j++) { comb[i][j] = comb[i - ][j] + comb[i - ][j - ]; comb[i][j] %= P; //cout << comb[i][j] << endl; } } }
逆元法
因为大部分题都有求余,可利用逆元的原理(没求余的题目,自己找一个比较大的素数作为P,也可以用逆元做)
线性递推求逆元
当$p$为质数时有$a^{-1}=(p-[p/a])\cdot (p\%a)^{-1}\%p$
求阶乘的逆元
根据通式:$C^{m}_{n}=\dfrac {n!}{m!\left( n-m\right) !}$,有$C^{m}_{n}=n!\cdot inv[m!] \cdot inv[(n-m)!]$
设 $finv(i)=inv(i\ !)$
则根据:$finv(i-1)=\frac{1}{\ (i-1)\ !}=\frac{1}{i\ !}\times i =finv(i)\times i$
有:$finv(i) = finv(i-1)\times inv(i)$
初始化时间复杂度$O(n)$,求$C^{m}_{n}$为$O(1)$
; ; ], Finv[N+], inv[N+];//fact是阶乘,Finv是阶乘的逆元 void init() { inv[] = ; //线性递推求逆元 ; i <= N; i++) { inv[i] = (P - P / i) * 1ll * inv[P % i] % P; } fact[] = Finv[] = ; ; i < N; i++) { fact[i] = fact[i - ] * 1ll * i % P;//求阶乘 Finv[i] = Finv[i - ] * 1ll * inv[i] % P;//求阶乘的逆元 } } int C(int n, int m) {//comb(n, m)就是C(n, m) || m > n) ; return fact[n] * 1ll * Finv[n - m] % P * Finv[m] % P; }
卢卡斯定理
现在有了新问题,如果$n$和$m$非常大,$p$为素数,比如求$C_n^m \% p \ ,\ n\leqslant 10^{18},m\leqslant 10^{18},p\leqslant 10^{9}$
$C_n^m\ \%\ p = C(n / p, m / p) * C(n\ \%\ p, m\ \%\ p)\ \%\ p$
或者写成这样更准确$Lucas(n,m)\ \%\ p=Lucas(n/p,m/p)*C(n\ \%\ p,m\ \%\ p)\ \%\ p$
证明请看此 lucas_百度百科,没仔细看证明,所以对不对我也不知道。
写成递归,代码就这么短:
LL Lucas(LL n, LL m, int p){ ; }
具体C的实现要看情况。
P较小时,打表
typedef long long ll; const int N = 1e5 ; ;//取一个小于N的素数 ll fact[P + ], inv[P + ], Finv[P + ];//阶乘打表 void init() { inv[] = ; //线性递推求逆元 ; i <= P; i++) { inv[i] = (P - P / i) * 1ll * inv[P % i] % P; } fact[] = Finv[] = ; ; i < P; i++) { fact[i] = fact[i - ] * 1ll * i % P;//求阶乘 Finv[i] = Finv[i - ] * 1ll * inv[i] % P;//求阶乘的逆元 } } ll C(ll n, ll m){//组合数C(n, m) % p ; return fact[n] * Finv[n - m] % P * Finv[m] % P; } ll Lucas(ll n, ll m){ ; }
P较大时,没法打表,用快速幂算逆元
typedef long long ll; const int N = 1e9 ; ; ll quickPower(ll a, ll b) { ll res = ; a %= P; while (b) { )res = (res % P) * (a % P) % P; a = (a % P) * (a % P) % P; b >>= ; } return res; } ll inv(ll x) {//x关于p的逆元,p为素数 ); } ll C(ll n, ll m) { ; ll up = , down = ;//分子分母; ; i <= n; i++) up = up * i % P; ; i <= m; i++) down = down * i % P; return up * inv(down) % P; } ll Lucas(ll n, ll m) { ); return C(n % P, m % P) * Lucas(n / P, m / P) % P; }
数论篇7——组合数 & 卢卡斯定理(Lucas)的更多相关文章
- 卢卡斯定理Lucas
卢卡斯定理Lucas 在数论中,\(Lucas\)定理用于快速计算\(C^m_n ~ \% ~p\),即证明\(C^m_n = \prod_{i = 0} ^kC^{m_i}_{n_i}\)其中\(m ...
- 【luogu P3807】【模板】卢卡斯定理/Lucas 定理(含 Lucas 定理证明)
[模板]卢卡斯定理/Lucas 定理 题目链接:luogu P3807 题目大意 求 C(n,n+m)%p 的值. p 保证是质数. 思路 Lucas 定理内容 对于非负整数 \(n\),\(m\), ...
- ACM数论之旅10---大组合数-卢卡斯定理(在下卢卡斯,你是我的Master吗?(。-`ω´-) )
记得前几章的组合数吧 我们学了O(n^2)的做法,加上逆元,我们又会了O(n)的做法 现在来了新问题,如果n和m很大呢, 比如求C(n, m) % p , n<=1e18,m<=1e18 ...
- 卢卡斯定理 Lucas (p为素数)
证明摘自:(我网上唯一看得懂的证明) https://blog.csdn.net/alan_cty/article/details/54318369 结论:(显然递归实现)lucas(n,m)=luc ...
- 洛谷.3807.[模板]卢卡斯定理(Lucas)
题目链接 Lucas定理 日常水题...sublime和C++字体死活不同步怎么办... //想错int范围了...不要被longlong坑 //这个范围现算阶乘比预处理快得多 #include &l ...
- CRT中国剩余定理 & Lucas卢卡斯定理
数论_CRT(中国剩余定理)& Lucas (卢卡斯定理) 前言 又是一脸懵逼的一天. 正文 按照道理来说,我们应该先做一个介绍. 中国剩余定理 中国剩余定理,Chinese Remainde ...
- 【数论】卢卡斯定理模板 洛谷P3807
[数论]卢卡斯定理模板 洛谷P3807 >>>>题目 [题目] https://www.luogu.org/problemnew/show/P3807 [输入格式] 第一行一个 ...
- 【Luogu3807】【模板】卢卡斯定理(数论)
题目描述 给定\(n,m,p(1≤n,m,p≤10^5)\) 求 \(C_{n+m}^m mod p\) 保证\(P\)为\(prime\) \(C\)表示组合数. 一个测试点内包含多组数据. 输入输 ...
- 【UOJ#275】组合数问题(卢卡斯定理,动态规划)
[UOJ#275]组合数问题(卢卡斯定理,动态规划) 题面 UOJ 题解 数据范围很大,并且涉及的是求值,没法用矩阵乘法考虑. 发现\(k\)的限制是,\(k\)是一个质数,那么在大组合数模小质数的情 ...
随机推荐
- js手动抛出异常
//js手动抛异常 if(!id){ throw new Error("选择标识无效"); } js抓取异常 try{ }catch (e) { console.log(e.msg ...
- docker镜像编码注意事项
第一步:下面这些话如果你不知道我在说什么,只管粘贴复制然后按回车键等待执行完成就行,一步步来不要着急. 首先安装docker,ubuntu18.04安装docker很简单只需要 一行命令 wget - ...
- Log4j Threshold指定输出等级&&Append指定是否追加内容
Threshold指定输出等级 有时候我们需要把一些报错ERROR日志单独存到指定文件 ,这时候,Threshold属性就派上用场了: Threshold属性可以指定日志level Log4j根据日志 ...
- [HeadFrist-HTMLCSS学习笔记]第二章深入了解超文本:认识HTML中的“HT”
[HeadFrist-HTMLCSS学习笔记]第二章深入了解超文本:认识HTML中的"HT" 敲黑板!!! 创建HTML超链接 <a>链接文本(此处会有下划线,可以单击 ...
- ASP.NET之MVC 微信公众号授权给第三方平台的技术实现流程(获取第三方平台access_token)
“出于安全考虑,在第三方平台创建审核通过后,微信服务器每隔10分钟会向第三方的消息接收地址推送一次component_verify_ticket,用于获取第三方平台接口调用凭据”.这是文档中的原话,也 ...
- Python 3.X 练习集100题 01
有以下几个数字:1.2.3.4.5,能组成多少个互不相同且无重复数字的三位数?都是多少? 方法1: import itertools from functools import reduce lyst ...
- Linux命令中service的用法
用途说明 service命令用于对系统服务进行管理,比如启动(start).停止(stop).重启(restart).查看状态(status)等.相关的命令还包括chkconfig.ntsysv等,c ...
- python实现根据前序与中序求后序
我就不板门弄斧了求后序 class Tree(): def __init__(self,x): self.value=x self.left=None self.right=None class So ...
- scratch教程:学做控制类积木
少儿编程中scratch很容易被小孩所接受,不管是从外观还是教程中,都符合少儿的兴趣,为此现在只要是开少儿编程课都会有scratch课程,今天娜娜姐小码王scratch培训机构就为大家分享,scrat ...
- teacher笔记
======= 总览 start ======= 1.素质教育以提高国民素质为根本宗旨4.素质教育是促进学生个性发展的教育5.素质教育是以培养学生的创新精神和事件能力为重点的教育2.素质教育是面向全体 ...