[笔记] 扩展\(Lucas\)定理

\(Lucas\)定理:\(\binom{n}{m} \equiv \binom{n/P}{m/P} \binom{n \% P}{m \% P}\pmod{P}\)\((P\ is \ prime)\)

Theory

那么如果\(p\)不是一个质数怎么办?

当我们需要计算\(C_n^m\mod p\),其中\(p = p_1^{q_1}\times p_2^{q_2}\times ...\times p_k^{q_k}\),我们可以求出:\(C_n^m\equiv a_i\pmod {p_i^{q_i}} (1\lt i \lt k)\)

然后对于方程组:

\(x\equiv a_i \pmod {p_i^{q_i}}(1\lt i\lt k)\)

我们可以求出满足条件的最小的\(x\),记为\(x_0\)那么我们有: \(C_n^m\equiv x_0\pmod p\)

但是,我们发现,\(p_i^{q_i}\)并不是一个素数,它是某个素数的某次方。

下面我们介绍如何计算\(C_n^m \mod p^t(t\ge2,p \ is \ prime)\)

我们知道,\(C_n^m=\frac {n!}{m!(n-m)!}\),若我们可以计算出\(m!\mod p^t\),我们就能计算出\((n-m)!\mod p^t\)以及\((n-m)!\mod p^t\).

我们不妨设\(x=n!\mod p^t,y=m!\mod p^t,z=(n-m)!\mod p^t,\)

那么答案就是

\(x\cdot inv(y,p^t)\cdot inv(z,p^t)\)那么下面问题就转化成如何计算\(n!\mod p^t\).

例如\(p=3,t=2,n=19\)

\(n!=1\times2\times3\times4\times5\times6\times7\times8\times ...\times19 \\ \ \ \ =(1\times2\times4\times5\times7\times8\times...\times16\times17\times19)\times(3\times6\times9\times12\times15\times18)\\\ \ \ =(1\times2\times4\times5\times7\times8\times...\times16\times17\times19)\times3^6\times(1\times2\times3\times4\times5\times6)\)

部分恰好是\((n/p)!\),于是递归即可。前半部分是以\(p^t\)为周期的\((1\times2\times4\times5\times7\times8)\equiv(10\times11\times13\times14\times16\times17)\pmod9\).下面是孤立的\(19\),可以知道孤立出来的长度不超过\(p^t\),于是直接计算即可。对于最后剩下的\(3^6\)这些数我们只要计算出\(n!,m!,(n-m)!\)里含有多少个\(p\)(不妨设\(x,y,z\)),那么\(x−y−z\)就是\(C_n^m\)中\(p\)的个数,直接计算就行。

Code

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cmath> typedef long long ll; const ll N = 1e6 + 5; ll g_x, g_y, cnt;
ll d[N], r[N]; ll q_pow(ll a, ll b, ll p){
ll w = 1;
while(b){
if(b & 1)
w = (a * w) % p;
b >>= 1;//1
a = (a * a) % p;
}
return w % p;
} ll exgcd(ll a, ll b){
if(b == 0){
g_x = 1;
g_y = 0;
return a;
}
ll gcd = exgcd(b, a % b);
ll t = g_x;
g_x = g_y;
g_y = t - a / b * g_y;
return gcd;
}/*exgcd求逆元 , ab + mt = 1, 前提: gcd(a, m) = 1;
用exgcd求逆元有个好处,不用让模数为素数,只要模数和这个a互质就好*/ ll inv(ll a, ll p){
exgcd(a, p);
return (g_x % p + p) % p;
} ll fac(ll n, ll pi, ll pk){
if(!n) return 1; //2 //递归边界
ll res = 1;
for(register ll i = 2; i <= pk; ++i){
if(i % pi)//3 pk
res = (res * i) % pk;
}/*因为循环节长度最多为pk,所以只需要算一遍pk,选这些数字里面不是pi倍数的数字
(因为是倍数的,我们已经处理掉了*/
res = q_pow(res, n / pk, pk);//有n/pk个循环
for(register ll i = 2; i <= n % pk; ++i){
if(i % pi)//3 pk
res = (res * i) % pk;//剩下的暴力做
}
return (res * fac(n / pi, pi, pk)) % pk; //递归继续
} void cal(ll n, ll m, ll pi, ll pk){
ll up = fac(n, pi, pk), d1 = fac(n - m, pi, pk), d2 = fac(m, pi, pk);
ll k = 0;
for(register ll i = n; i; i /= pi) k += i / pi;
for(register ll i = m; i; i /= pi) k -= i / pi;
for(register ll i = n - m; i; i /= pi) k -= i / pi;//这三行都是统计pi倍数的个数,后两个要减去是因为组合数的计算不就有个除嘛
r[++cnt] = q_pow(pi, k, pk) % pk * up % pk * inv(d1, pk) % pk * inv(d2, pk) % pk;
d[cnt] = pk;//CRT,r表示余数,d表示除数
} ll mul(ll a, ll b, ll p){
ll f = 1;
if(a < 0) f = -f, a = -a;
if(b < 0) f = -f, b = -b;
ll w = 0;
while(b){
if(b & 1)
w = (w + a) % p;
b >>= 1;
a = (a + a) % p;
}
return w * f;
}//龟速乘 ll exCRT(){
for(register ll i = 2; i <= cnt; ++i){
ll C = r[1] - r[i];
ll D = exgcd(d[i], d[1]);
if(C % D) return -1;
ll k1 = mul(g_y, C / D, d[1] / D * d[i]);
ll x0 = mul(-k1 , d[1], d[1] / D * d[i] ) + r[1];
d[1] = d[1] / D * d[i], r[1] = x0;
r[1] = (r[1] % d[1] + d[1]) % d[1];
}
return r[1];//很好的exCRT
} ll exlucas(ll n, ll m, ll p){
ll lim = sqrt(p) + 1;
ll tmp = p;
ll pk;
for(register ll i = 2; i <= lim; ++i){
if(tmp % i == 0){
pk = 1;
while(tmp % i == 0){
pk *= i;
tmp /= i;//为了得出pk
}
cal(n, m, i, pk);
}
}//唯一分解
if(tmp > 1) cal(n, m, tmp, tmp);//4 唯一分解后可能会留下一个大素数
return exCRT() % p;//5 pk
} int main(){
ll n, m, p;
scanf("%lld %lld %lld", &n, &m, &p);
printf("%lld\n", exlucas(n, m, p));
}

Wrong

  1. 快速幂中的指数忘记右移
  2. \(fac\)递归边界忽略掉了
  3. 循环节计算时,是取那些不是\(pi\)倍数的,而不是不是\(pk\)倍数的
  4. \(exCRT\)最后模的是\(p\),不是\(pk\)!!!

爱你哟

[笔记] 扩展Lucas定理的更多相关文章

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

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

  2. 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 ...

  3. 【learning】 扩展lucas定理

    首先说下啥是lucas定理: $\binom n m \equiv \binom {n\%P} {m\%P} \times \binom{n/P}{m/P} \pmod P$ 借助这个定理,求$\bi ...

  4. BZOJ - 2142 礼物 (扩展Lucas定理)

    扩展Lucas定理模板题(貌似这玩意也只能出模板题了吧~~本菜鸡见识鄙薄,有待指正) 原理: https://blog.csdn.net/hqddm1253679098/article/details ...

  5. [bzoj2142]礼物(扩展lucas定理+中国剩余定理)

    题意:n件礼物,送给m个人,每人的礼物数确定,求方案数. 解题关键:由于模数不是质数,所以由唯一分解定理, $\bmod  = p_1^{{k_1}}p_2^{{k_2}}......p_s^{{k_ ...

  6. Lucas定理和扩展Lucas定理

    1.Lucas定理 首先给出式子:\(C_n^m\%p = C_{\lfloor\frac{n}{p}\rfloor}^{\lfloor\frac{m}{p}\rfloor} * C_{n\%p}^{ ...

  7. Ceizenpok’s formula Gym - 100633J 扩展Lucas定理 + 中国剩余定理

    http://codeforces.com/gym/100633/problem/J 其实这个解法不难学的,不需要太多的数学.但是证明的话,我可能给不了严格的证明.可以看看这篇文章 http://ww ...

  8. 扩展Lucas定理

    (1)Lucas定理:p为素数,则有: (2)证明: n=(ak...a2,a1,a0)p = (ak...a2,a1)p*p + a0 =  [n/p]*p+a0,m=[m/p]*p+b0其次,我们 ...

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

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

随机推荐

  1. Python——处理CSV、PDF文件

    一.CSV文件处理 (1)读取 import csv filename = "E:/GitHub/Python-Learning/LIVE_PYTHON/2018-06-05/学位英语成绩合 ...

  2. Linux系统诊断必备技能之三:查看信息系统常用命令

    一.概述 Linux操作系统的学习中,CLI下进行操作,需要掌握大量命令,Linux的命令有很多,对于命令的学习大家记住只能是熟能生巧,所以现在把日常使用命令为大家罗列一部分,仅供参考. 二.常用命令 ...

  3. 缓冲区溢出实验 5 Snprintf

    实验环境.代码.及准备 https://www.cnblogs.com/lqerio/p/12870834.html vul5 Snprintf函数,百度百科: 将可变个参数(...)按照format ...

  4. Leetcode(83)-删除排序链表中的重复元素

    给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次. 示例 1: 输入: 1->1->2 输出: 1->2 示例 2: 输入: 1->1->2->3-&g ...

  5. React hox

    React hox https://github.com/umijs/hox

  6. Web 实时通信方案 All In One

    Web 实时通信方案 All In One HTTP 轮询, 单向通信,开销大 HTTP 长轮询, 单向通信,开销较小 WebSocket,双向通信,开销小 (TCP 高延迟,保证数据完整性) Ser ...

  7. ADN vs CDN All In One

    ADN vs CDN All In One Netlify & JAMstack https://app.netlify.com/teams/xgqfrms/sites ADN Applica ...

  8. Web Components All In One

    Web Components All In One Web Components https://www.webcomponents.org/ HTML Template Custom Element ...

  9. Python module all in one

    Python module all in one Python Modules https://docs.python.org/3/tutorial/modules.html Fibonacc # F ...

  10. 2020 front-end interview

    2020 front-end interview https://juejin.im/post/5e083e17f265da33997a4561 xgqfrms 2012-2020 www.cnblo ...