『Lucas定理以及拓展Lucas』
<更新提示>
<第一次更新>
<正文>
Lucas定理
在『组合数学基础』中,我们已经提出了\(Lucas\)定理,并给出了\(Lucas\)定理的证明,本文仅将简单回顾,并给出代码。
\(Lucas\)定理:当\(p\)为质数时,\(C_n^m\equiv C_{n\ mod\ p}^{m\ mod\ p}*C_{n/p}^{m/p}(mod\ p)\)。
在计算模域组合数时,如果模数较小,那么就可以尝试使用\(Lucas\)定理来递归求解,其时间复杂度为\(O(plog_p\min(n,m))\)。
\(Code:\)
inline long long Lucas(long long u,long long d)
{
if (u<=Mod&&d<=Mod)return C(u,d) % Mod;
else return Lucas(u/Mod,d/Mod) * C(u%Mod,d%Mod) % Mod;
}
本文给出了一种递归写法,由于取模操作的存在,在组合数计算函数\(C\)内也需要进行一些特判,避免一些无意义式子的计算,影响答案。
\(Code:\)
inline long long C(long long u,long long d)
{
if ( u>d || u<0 || d<0 )return 0LL;
//...
}
关于组合数的计算,我们也有多种方法,常用的几种如下:
\(1.\) 当\(n\),\(m\)都比较小的时候,可以根据组合数的阶乘计算公式来预处理\(n\),\(m\)范围以内的阶乘以及阶乘的逆元,然后根据询问\(O(1)\)地回答组合数。
\(2.\) 当\(n\)的范围较大,\(m\)的范围较小时,由于不适合预处理,所以我们可以直接利用有关\(m\)组合数计算式\(C_n^m=\frac{n*(n-1)*...*(n-m+1)}{m*(m-1)*...*1}\)来模拟计算,同理,分母利用逆元操作即可,时间复杂度\(O(m)\)。
Exlucas算法
与之对应的,\(Exlucas\)算法是一种用来解决与\(Lucas\)定理形式很像但更具有一般性的问题的算法。为什么不叫\(Exlucas\)定理而叫\(Exlucas\)算法呢,是因为这个算法和\(Lucas\)定理没什么关系,只是一个数论算法罢了。
对于求解模域组合数\(C_n^m\%p\),当\(p\)不一定是质数时,可以使用\(Exlucas\)算法求解。
对于这样一个问题,我们考虑对模数进行分解,设\(p=\prod_{i=1}^kp_i^{a_i}\),答案\(x=C_n^m\%p\),则可以得到$$x\equiv C_n^ m(mod\ p_i^{a_i})$$
这是一个线性同余方程组,可以使用中国剩余定理求解。
那么现在我们的问题就转换成了求解\(C_n^m\%p_i^{a_i}\)。将组合数写为阶乘的计算式,即\(C_n^m=\frac{n!}{m!(n-m)!}\)。
因为\(\frac{n!}{m!(n-m)!}\)与\(p_i^{a_i}\)不可避免的会存在公约数,所以不能直接使用\(Exeuclid\)等算法来求解逆元,那么我们就要考虑把\(\frac{n!}{m!(n-m)!}\)中有关\(p_i\)的项都提取掉,利用\(\frac{n!}{m!(n-m)!}\)是整数这一特点将分子该项的指数直接减掉分母该项的指数,再求解其余部分以及逆元,最后就能避免不互质的情况从而求解答案。
先考虑一个简单的问题,如何计算一个形如\(n!\)的数中含有多少个因子\(p\),则和阶乘分解一题类似,若设\(f(n)\)表示\(n!\)中含有因子\(p\)的个数,则有:
\]
简单地利用\(for\)循环求解即可。
求得阶乘中因子\(p_i\)的数量后,我们的问题就变成为如何求解\(n!\)中除去所有\(p_i\)后取模\(p_i^{a_i}\)的值。对于每一项,这又需要我们分两种情况考虑:
\(1.\) 该项是除去\(p_i\)后得到的,我们将所有这样的项放在一起发现,发现除去\(p_i\)后,剩下的系数乘积也是一个阶乘,使用递归求解。
\(2.\) 该项是阶乘中原本的一项,除去情况\(1.\),我们发现阶乘中若干个连续的项在模\(p_i^{a_i}\)意义下恰好构成了循环节,其长度不超过\(p_i^{a_i}\),先暴力计算一个循环节,然后快速幂即可。对于不包括在完整循环节中的项,由于其长度小于循环节,可以暴力计算。
然后就能将求得的答案通过计算逆元求解,最后,乘上提取出的\(p_i\)剩余的若干次方即可。
考虑一个简单的例子就能加深理解:
求解\(n!\ mod\ p_i^{p_i}\),此时,\(n=19\),\(p_i=3\),\(a_i=2\)。
\\=(1*2*4*5*7*8)^2*19*(3^6*6!)
\]
可以证明,其时间复杂度与\(O(plog_2p)\)同级。
\(Code:\)
#include <bits/stdc++.h>
using namespace std;
const int SIZE=300;
long long A,B,Mod,m[SIZE],r[SIZE];
inline void input(void)
{
scanf("%lld%lld%lld",&A,&B,&Mod);
//计算C(A,B)%Mod
}
inline long long power(long long a,long long b,long long p)
{
long long res = 1;
while (b)
{
if (1&b)res = res * a % p;
b >>= 1;
a = a * a % p;
}
return res;
}
inline long long Exeuclid(long long a,long long &x,long long b,long long &y,long long c)
{
if (!b){x=c/a,y=0;return a;}
else
{
long long p = Exeuclid(b,x,a%b,y,c);
long long x_ = x , y_ = y;
x = y_ , y = x_ - a/b * y_;
return p;
}
}
inline long long inv(long long a,long long p)
{
long long x_,y_;
Exeuclid(a,x_,p,y_,1);
return (x_+p)%p;
}
inline long long calc(long long x,long long val,long long p)
{
//计算x!中除去val后模p意义下的值
if (!x)return 1;
long long res = 1 , last = x%p;
for (long long i=1;i<=p;i++)
if (i%val)res = res * i % p;
res = power(res,x/p,p);
for (long long i=1;i<=last;i++)
if (i%val)res = res * i % p;
return res * calc(x/val,val,p) % p;
}
inline long long C(long long d,long long u,long long val,long long Pow)
{
long long mulup=calc(d,val,Pow) , k=0;
long long muldown1=calc(u,val,Pow) , muldown2=calc(d-u,val,Pow);
for (long long i=d;i;i/=val)k+=i/val;
for (long long i=u;i;i/=val)k-=i/val;
for (long long i=d-u;i;i/=val)k-=i/val;
//计算剩余的val的指数
return mulup * inv(muldown1,Pow) % Pow * inv(muldown2,Pow) % Pow * power(val,k,Pow) % Pow;
}
inline long long CRT(int cnt)
{
long long m_ = Mod , M[SIZE] = {} , t[SIZE] = {} , res = 0;
for (int i=1;i<=cnt;i++)
M[i] = m_ / m[i];
for (int i=1;i<=cnt;i++)
{
long long y;
Exeuclid(M[i],t[i],m[i],y,1);
res = (res + r[i] % m_ * M[i] % m_ * t[i] % m_) % m_;
}
return ( res % m_ + m_ ) % m_;
}
inline long long Exlucas(void)
{
int temp = Mod , cnt = 0 ;
for (long long i=2;i*i<=Mod;i++)
{
if (temp%i==0)
{
m[++cnt] = 1;
while (temp%i==0)
temp /= i , m[cnt] *= i;
r[cnt] = C(A,B,i,m[cnt]);
}
}
if (temp>1) m[++cnt] = temp , r[cnt] = C(A,B,temp,m[cnt]);
return CRT(cnt);
}
int main(void)
{
input();
printf("%lld\n",Exlucas());
return 0;
}
<后记>
『Lucas定理以及拓展Lucas』的更多相关文章
- lucas定理及其拓展的推导
lucas定理及其拓展的推导 我的前一篇博客-- lucas定理 https://mp.csdn.net/mdeditor/100550317#主要是给出了lucas的结论和模板,不涉及推导. 本篇文 ...
- Lucas定理和扩展Lucas定理
1.Lucas定理 首先给出式子:\(C_n^m\%p = C_{\lfloor\frac{n}{p}\rfloor}^{\lfloor\frac{m}{p}\rfloor} * C_{n\%p}^{ ...
- 【luogu P3807】【模板】卢卡斯定理/Lucas 定理(含 Lucas 定理证明)
[模板]卢卡斯定理/Lucas 定理 题目链接:luogu P3807 题目大意 求 C(n,n+m)%p 的值. p 保证是质数. 思路 Lucas 定理内容 对于非负整数 \(n\),\(m\), ...
- 【bzoj1951】【古代猪文】Lucas定理+欧拉定理+孙子定理
(上不了p站我要死了,当然是游戏原画啊) Description (题面倒是很有趣,就是太长了) 题意: 一个朝代流传的猪文文字恰好为N的k分之一,其中k是N的一个正约数(可以是1和N).不过具体是哪 ...
- 拓展lucas结论及模板
lucas及其拓展 模板题 洛谷 P4720 本文侧向结论和代码实现, 推导请转至lucas定理及其拓展的推导 https://blog.csdn.net/yuyilahanbao/article/d ...
- hdu3037 Lucas定理
Lucas定理 Lucas(n,m,p)=c(n%p,m%p)* Lucas(n/p,m/p,p),其中lucas(n,m,p)=C(n,m)%p (这里的除号是整除) 证明——百度百科 题意:求n个 ...
- HDU 5226 Tom and matrix(组合数学+Lucas定理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5226 题意:给一个矩阵a,a[i][j] = C(i,j)(i>=j) or 0(i < ...
- [CodeVs1515]跳(lucas定理+费马小定理)
嘿嘿嘿好久没写数学题了,偶尔看到一道写一写... 题目大意:一个(n+1)*(m+1)[0<=n, m<=10^12,n*m<=10^12]的矩阵,C(0,0)=1,C(x,y)=C ...
- hdu 3037 费马小定理+逆元除法取模+Lucas定理
组合数学推推推最后,推得要求C(n+m,m)%p 其中n,m小于10^9,p小于1^5 用Lucas定理求(Lucas定理求nm较大时的组合数) 因为p数据较小可以直接阶乘打表求逆元 求逆元时,由费马 ...
随机推荐
- 大型进销存管理系统源码 家电业 电器类进销存 asp.net C#框架
系统详细信息点击查看 系统功能模块,系统管理: 部门管理 ,用户管理 ,角色管理 ,菜单管理 ,参数设置 商品管理: 类型管理 ,品牌管理 ,名称管理 ,型号管理 ,仓库管理 ,商家管理 ,单位管理 ...
- logistic 回归
logistic回归 1.算法思想 根据给定的数据集确定分类的边界.这个分类的边界就是我们所要求的回归函数. 所谓的回归其实就是最佳拟合,回归函数就是确定最佳回归参数,然后对不同的特征赋予不同的权重 ...
- servlet什么时候被实例化?【转】
如果没有设置loadOnStartup,则第一次请求的时候实例化 分三种情况:loadOnStartup < 0 即负数的情况下,web容器启动的时候不做实例化处理,servlet首次被调用时做 ...
- vue项目 构建 打包 发布 三部曲
一.vue项目的创建 1.首先第一肯定是要有Node.js及npm这个不多说了2.安装脚手架 此时可以直接浏览-但是现在肯定有很多小白想将他发布到gitHub上并可以浏览,使用vue全家桶制作自己的博 ...
- win10汇编环境的搭建
第一步:下载DOSBox0.74-win32-installer 可以去官网:http://www.dosbox.com/ 或者链接:https://pan.baidu.com/s/1UA77qTLO ...
- 基于ubuntu16.04快速构建Hyperledger Fabric网络
前言 最近在参加一个比赛,使用到了区块链的开源软件hyperledger,由于之前从未接触过区块链,以及和区块链开发相关的内容,所有在网上查阅了大量的资料,并且通过学习yeasy(杨宝华)开源的入门书 ...
- python_自定日历
>>> from datetime import date>>> daysOfMonth=[31,28,31,30,31,30,31,31,30,31,30,31] ...
- SSM-MyBatis-17:Mybatis中一级缓存(主要是一级缓存存在性的证明,增删改对一级缓存会造成什么影响)
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 缓存------------------------------------------> 很熟悉的一个 ...
- Zookeeper vs etcd vs Consul
Zookeeper vs etcd vs Consul [编者的话]本文对比了Zookeeper.etcd和Consul三种服务发现工具,探讨了最佳的服务发现解决方案,仅供参考. 如果使用预定义的端口 ...
- Spring boot +Spring Security + Thymeleaf 认证失败返回错误信息
[Please make sure to select the branch corresponding to the version of Thymeleaf you are using] Stat ...