初见安~这里是数论专题(6)【详见数论专栏

本篇有前置知识点需要掌握,建议先了解下:费马小定理,中国剩余定理,乘法逆元

一、Lucas定理

Lucas定理用于求解的组合数取模的问题。其中p为质数

组合数取模我们可以用分解质因数再分别相乘取模相加,但有时也很容易超时。

Lucas定理中,将n和m转化为p进制,即有:

则有:

这里问题就来了——组合数取模,最后还是转化成了一堆组合数的累乘,有什么有吗???

其实就相当于把一个很大的乘法分解了,使其不容易越界,不容易超时。

而我们把C(n, m)化小了过后,可以选择直接暴力用组合公式:

当然分子和分母是有可以化简的部分的,可以化简为

其中要除以m!,我们可以直接乘m的逆元。而根据费马小定理(传送门同逆元),p为质数,我们可以得出:设x = m!,则有。而根据逆元的性质,我们设x的逆元为a,必有。两式联立便可以得到:

。所以我们用快速幂就可以求得x的逆元了。

核心代码实现如下:

typedef long long ll;//求其逆元
ll mod_power(ll a, ll b, ll p)
{ll ans = 1;while(b){if(b & 1) ans = ans * a % p;a = a * a % p;b >>= 1;}return ans;
}//求组合数。因为分解得较小了,所以可以用暴力
ll C(ll n, ll m, ll p)
{if(m > n) return 0;ll c1 = 1, c2 = 1;for(int i = n - m + 1; i <= n; i++)//由组合数公式化简得c1 = c1 * i % p;for(int i = 2; i <= m; i++)c2 = c2 * i % p;return c1 * mod_power(c2, p - 2, p) % p;//乘其逆元,是一种优化
}//Lucas定理
ll Lucas(ll n, ll m, ll p)
{if(!m) return 1;return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;//累乘,递归实现
}

二、扩展Lucas定理(exLucas)

各种的所谓扩展,都是在原有的基础上去掉一些限制条件。比如——扩展Lucas定理,就是求解的问题,且不保证p为质数

很明显,如果p过大,会很容易导致我们求组合数的时候越界,而且不是质数,不能单纯地用Lucas定理。所以——既然不是质数,变成质数就行了嘛。怎么变?分解质因数

(1)我们将p质因数分解为t个质数的k次方的乘积:

然后运用到一个显而易见的结论——来建立同余方程:

又因为满足mod的数为分解后的质因数的幂,所以互质,可以用中国剩余定理求解。看起来你还不是要求,而且求很多次。事实上,因为mod的数已经分解了,所以已经是比暴力求阶乘要优很多了。所以这就是我们的第一步。

(2)接下来我们要求了。当然,入口可以直接设立在分解质因数的时候。参考Lucas定理的思路,我们这里用排列组合公式来化简。同样的要运用到逆元。但是——这里要mod的数并不是质数,如果我们为了求逆元而用费马小定理去套用欧拉函数,那是一定复杂化了的。不如直接点,就像把p变成质数一样——我们也把n!、m!和(n - m)!变成和pi的ki次方互质的数,也就是除以其最大包含有pi^ki的约数。(比如100和5不互质,但100/(5^2)= 4就可以了)就可以转化为:(这里的k和第一步中质因数分解的k没有任何关系)

。这样一来我们就可以用到逆元了——求的逆元。当然, 因为会用到多次,如果调用快速幂就不方便了,所以我们选用原始一点的扩欧定理,将其转化为线性同余方程来求解。【可能用快速幂也行的通】

(3)在第二步的基础上,我们又将问题转化为了——如何求解(这里就简写p和k了,k是(1)中的意义,a是(2)中的k,是那么个意思就行了)。很明显,p^a我们可以算,p^k我们可以传过来,所以关键就在于n!。暴力?绝 对 不 行。不如找找有没有能简化的步骤。

举个例子来看看吧——19! % 3^2。

其中,

不难发现,可以把3的倍数提出来打包一下变成:

也就是

至于后面那一串,我们展开来看(建议手算),可以发现:每3^2长度mod 3^2的值都是一样的。也就是说:

所以至此,我们可以把求阶乘的这一步分解为三个部分——p幂次的阶乘*p,n / (p^k)个同余的式子和最后剩下的n % (p^k)的部分。其中求p幂次的阶乘,我们亦可以递归调用求阶乘的fac函数。所以到这里——这个问题就解决啦!!!其中有不少为了优化而略显复杂的操作,但逻辑上还是十分清晰的。

下面上代码——【过程太长,就上完整代码了】

#include<bits/stdc++.h>
using namespace std;
long long c[1000005], a[1000005];
long long power(long long a, long long b, long long p)//快速幂
{long long ans = 1;while(b){if(b & 1) ans = ans * a % p;a = a * a % p;b >>= 1;}return ans;
}long long fac(long long n, long long p, long long pk)//求阶乘
{if(!n) return 1;long long ans = 1;for(int i = 1; i < pk; i++)if(i % p) ans = ans * i % pk; //同余部分 ans =  power(ans, n / pk, pk);for(int i = 1; i <= n % pk; i++)//剩余无法凑同余的部分if(i % p) ans = ans * i % pk; return ans * fac(n / p, p, pk) % pk;
}long long exgcd(long long a, long long b, long long &x, long long &y)
{if(!b){x = 1, y = 0;return a;}long long xx, yy, g = exgcd(b, a % b, xx, yy);x = yy;y = xx - a / b * yy;return g;
}long long inv(long long a, long long p)//求逆元
{long long y, x;exgcd(a, p, x, y);//扩欧定理求解return (x % p + p) % p;
} long long C(long long n, long long m, long long p, long long pk)//求组合数
{if(m > n) return 0;long long f1 = fac(n, p, pk), f2 = fac(m, p, pk), f3 = fac(n - m, p, pk), cnt = 0;//因为要求逆元,所以三个的阶乘都要老老实实算出来for(long long i = n; i; i /= p)cnt += i / p;       for(long long i = m; i; i /= p)cnt -= i / p;for(long long i = n - m; i; i /= p)cnt -= i / p;//这里不能用费马,p不为素数。//cnt计算的是step2中的(k1 - k2 - k3)return f1 * inv(f2, pk) % pk * inv(f3, pk) % pk * power(p, cnt, pk) % pk;
}long long CRT(long long cnt)//中国剩余定理
{long long M = 1, ans = 0;for(int i = 1; i <= cnt; i++)M *= c[i];//p的值变了,所以要重新计算for(int i = 1; i <= cnt; i++){ans = (ans + a[i] * (M / c[i]) % M * inv(M / c[i], c[i]) % M) % M;} return ans;
}long long exlucas(long long n, long long m, long long p)
{long long temp, cnt= 0;for(int i = 2; p > 1 && i <= p / i; i++)//分解质因数{long long tmp = 1; while (p % i == 0)p /= i, tmp *= i;if (tmp > 1)//有这个p a[++cnt] = C(n, m, i, tmp), c[cnt] = tmp;//c里存pk }if(p > 1) c[++cnt] = p, a[cnt] = C(n, m, p, p);return CRT(cnt);
}int main()
{long long m, n, p;scanf("%lld%lld%lld", &n, &m, &p);printf("%lld", exlucas(n, m, p));
}

看起来代码真的很 长。其实只要理解了推导过程就还是很好记的~

以上就是关于Lucas定理的内容啦~

迎评:)
——End——

专题·Lucas定理【including Lucas定理,扩展Lucas相关推荐

  1. 2015 ICL, Finals, Div. 1 Ceizenpok’s formula(组合数取模,扩展lucas定理)

    J. Ceizenpok's formula time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  2. [学习笔记]扩展LUCAS定理

    可以先做这个题[SDOI2010]古代猪文 此算法和LUCAS定理没有半毛钱关系. [模板]扩展卢卡斯 不保证P是质数. $C_n^m=\frac{n!}{m!(n-m)!}$ 麻烦的是分母. 如果互 ...

  3. Lucas定理与扩展Lucas

    之前看了乘法逆元(详见除法取模与逆元),发现不能处理不互质的情况,于是去找方法,最后找到了Lucas定理... 虽然与期待中的不一样,但是还是非常有用的. (1)Lucas定理: 若p为素数,则有: ...

  4. Lucas定理扩展Lucas

    Lucas定理 求解 C n m m o d    p C_n^m\mod p Cnm​modp (p为素数) 蒟蒻不会证明,记着递推公式就好=_= L u c a s ( n , m ) = C ( ...

  5. lucas定理及扩展lucas定理

    还有一篇关于lucas定理的比较好的文章:关于LUCAS二项式系数同余定理的一些推广 转载原文链接:http://www.cnblogs.com/jianglangcaijin/p/3446839.h ...

  6. BZOJ 4338 糖果(扩展Lucas定理+CRT)

    题目链接:BZOJ 4338 题目大意:用数字1~k填一个n*m的表格,每种数字可用任意次,要求每行数字1~m列单调不减,任意两行不完全相同,求方案数对P取模的值. 题解:扩展Lucas+CRT模板题 ...

  7. 扩展Lucas定理 扩展Lucas板子

    题意概述:多组询问,给出N,K,M,要求回答C(N,K)%M,1<=N<=10^18,1<=K<=N,2<=M<=10^6 分析: 模数不为质数只能用扩展Lucas ...

  8. 【bzoj1951】【古代猪文】Lucas定理+欧拉定理+孙子定理

    (上不了p站我要死了,当然是游戏原画啊) Description (题面倒是很有趣,就是太长了) 题意: 一个朝代流传的猪文文字恰好为N的k分之一,其中k是N的一个正约数(可以是1和N).不过具体是哪 ...

  9. bzoj 4830: [Hnoi2017]抛硬币 [范德蒙德卷积 扩展lucas]

    4830: [Hnoi2017]抛硬币 题意:A投a次硬币,B投b次硬币,a比b正面朝上次数多的方案数,模\(10^k\). \(b \le a \le b+10000 \le 10^{15}, k ...

最新文章

  1. python3.7和3.8的区别-Python 3.8 有什么新变化
  2. 设计模式-Factory Method Pattern
  3. SQL 创建数据库、表以及索引
  4. 大数据可视化技术挑战和措施
  5. mac版有道云笔记切换笔记后内容仍展示前一个笔记内容问题解决
  6. 基于树莓派的遥控开锁装置
  7. 西门子触摸屏数据历史数据记录_西门子触摸屏参数跟数据简单说明
  8. Win11 安装 Linux 子系统
  9. OpenGL (太阳,地球,月亮 +太阳系八大行星)
  10. 使用JS监听键盘按下事件(keydown event)
  11. 预训练模型在金融 NLP场景下的应用
  12. 导入导出excel表格EasyExcel操作
  13. 修改ARM开发板IP地址
  14. SAP那些事-理论篇-3-SAP到底是个什么东东
  15. 用ps制作动态的地球旋转图片
  16. 在总账模块结账的时候提示总账和明细账对账不平结不了账
  17. pycharm贪吃蛇
  18. 实战解密热门js加密v6
  19. 达梦数据库导入导出操作步骤
  20. rc列联表_R实战 第十篇:列联表和频数表

热门文章

  1. day11C语言递归
  2. 转行|什么是游戏建模??小本本记下来
  3. 苹果供应商的痛苦与快乐,赚钱不容易,却被迫着往前行
  4. JAVA项目linux僵尸进程_linux杀死僵尸进程
  5. 常用DNS服务器提供商
  6. 贝叶斯方法及电影评价实例
  7. NER中的一些编码器与解码器
  8. python绘制折线图保存_Python利用matplotlib绘制折线图的新手教程
  9. Tyk API网关介绍及安装说明
  10. B站6月榜单丨飞瓜数据UP主成长排行榜(哔哩哔哩平台)发布!