1.当n,m都很小的时候可以利用杨辉三角直接求。
C(n,m)=C(n-1,m)+C(n-1,m-1);

2、n和m较大,但是p为素数的时候

Lucas定理是用来求 c(n,m) mod p,p为素数的值

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递归出口为m=0时返回1

求C(n%p, m%p)%p的时候,此处写成C(n, m)%p(p是素数,n和m均小于p)

C(n, m)%p = n! / (m ! * (n - m )!) % p = n! * mod_inverse[m! * (n - m)!, p] % p

由于p是素数,有费马小定理可知,m! * (n - m)! 关于p的逆元就是m! * (n - m)!的p-2次方。

p较小的时候预处理出1-p内所有阶乘%p的值,然后用快速幂求出逆元,就可以求出解。p较大的时候只能逐项求出分母和分子模上p的值,然后通过快速幂求逆元求解。

P较大,不打表:

 ll pow(ll a, ll b, ll m)
{
ll ans = ;
a %= m;
while(b)
{
if(b & )ans = (ans % m) * (a % m) % m;
b /= ;
a = (a % m) * (a % m) % m;
}
ans %= m;
return ans;
}
ll inv(ll x, ll p)//x关于p的逆元,p为素数
{
return pow(x, p - , p);
}
ll C(ll n, ll m, ll p)//组合数C(n, m) % p
{
if(m > n)return ;
ll up = , down = ;//分子分母;
for(int i = n - m + ; i <= n; i++)up = up * i % p;
for(int i = ; i <= m; i++)down = down * i % p;
return up * inv(down, p) % p;
}
ll Lucas(ll n, ll m, ll p)
{
if(m == )return ;
return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}

P较小,打表:

 const int maxn = 1e5 + ;
ll fac[maxn];//阶乘打表
void init(ll p)//此处的p应该小于1e5,这样Lucas定理才适用
{
fac[] = ;
for(int i = ; i <= p; i++)
fac[i] = fac[i - ] * i % p;
}
ll pow(ll a, ll b, ll m)
{
ll ans = ;
a %= m;
while(b)
{
if(b & )ans = (ans % m) * (a % m) % m;
b /= ;
a = (a % m) * (a % m) % m;
}
ans %= m;
return ans;
}
ll inv(ll x, ll p)//x关于p的逆元,p为素数
{
return pow(x, p - , p);
}
ll C(ll n, ll m, ll p)//组合数C(n, m) % p
{
if(m > n)return ;
return fac[n] * inv(fac[m] * fac[n - m], p) % p;
}
ll Lucas(ll n, ll m, ll p)
{
if(m == )return ;
return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}

3、n,m较大且p不为素数的时候

扩展Lucas定理:

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + ;
const int mod = 1e9 + ;
ll pow(ll a, ll b, ll m)
{
ll ans = ;
a %= m;
while(b)
{
if(b & )ans = (ans % m) * (a % m) % m;
b /= ;
a = (a % m) * (a % m) % m;
}
ans %= m;
return ans;
}
ll extgcd(ll a, ll b, ll& x, ll& y)
//求解ax+by=gcd(a, b)
//返回值为gcd(a, b)
{
ll d = a;
if(b)
{
d = extgcd(b, a % b, y, x);
y -= (a / b) * x;
}
else x = , y = ;
return d;
}
ll mod_inverse(ll a, ll m)
//求解a关于模上m的逆元
//返回-1表示逆元不存在
{
ll x, y;
ll d = extgcd(a, m, x, y);
return d == ? (m + x % m) % m : -;
} ll Mul(ll n, ll pi, ll pk)//计算n! mod pk的部分值 pk为pi的ki次方
//算出的答案不包括pi的幂的那一部分
{
if(!n)return ;
ll ans = ;
if(n / pk)
{
for(ll i = ; i <= pk; i++) //求出循环节乘积
if(i % pi)ans = ans * i % pk;
ans = pow(ans, n / pk, pk); //循环节次数为n / pk
}
for(ll i = ; i <= n % pk; i++)
if(i % pi)ans = ans * i % pk;
return ans * Mul(n / pi, pi, pk) % pk;//递归求解
} ll C(ll n, ll m, ll p, ll pi, ll pk)//计算组合数C(n, m) mod pk的值 pk为pi的ki次方
{
if(m > n)return ;
ll a = Mul(n, pi, pk), b = Mul(m, pi, pk), c = Mul(n - m, pi, pk);
ll k = , ans;//k为pi的幂值
for(ll i = n; i; i /= pi)k += i / pi;
for(ll i = m; i; i /= pi)k -= i / pi;
for(ll i = n - m; i; i /= pi)k -= i / pi;
ans = a * mod_inverse(b, pk) % pk * mod_inverse(c, pk) % pk * pow(pi, k, pk) % pk;//ans就是n! mod pk的值
ans = ans * (p / pk) % p * mod_inverse(p / pk, pk) % p;//此时用剩余定理合并解
return ans;
} ll Lucas(ll n, ll m, ll p)
{
ll x = p;
ll ans = ;
for(ll i = ; i <= p; i++)
{
if(x % i == )
{
ll pk = ;
while(x % i == )pk *= i, x /= i;
ans = (ans + C(n, m, p, i, pk)) % p;
}
}
return ans;
} int main()
{
ll n, m, p;
while(cin >> n >> m >> p)
{
cout<<Lucas(n, m, p)<<endl;
}
return ;
}

组合数取模方法总结(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定理介绍

    转载https://www.cnblogs.com/fzl194/p/9095177.html 组合数取模方法总结(Lucas定理介绍) 1.当n,m都很小的时候可以利用杨辉三角直接求. C(n,m) ...

  3. CF451E Devu and Flowers (隔板法 容斥原理 Lucas定理 求逆元)

    Codeforces Round #258 (Div. 2) Devu and Flowers E. Devu and Flowers time limit per test 4 seconds me ...

  4. 【Gym 100947E】Qwerty78 Trip(组合数取模/费马小定理)

    从(1,1)到(n,m),每次向右或向下走一步,,不能经过(x,y),求走的方案数取模.可以经过(x,y)则相当于m+n步里面选n步必须向下走,方案数为 C((m−1)+(n−1),n−1) 再考虑其 ...

  5. Codeforces 57C (1-n递增方案数,组合数取模,lucas)

    这个题相当于求从1-n的递增方案数,为C(2*n-1,n); 取模要用lucas定理,附上代码: #include<bits/stdc++.h> using namespace std; ...

  6. [UOJ 275/BZOJ4737] 【清华集训2016】组合数问题 (LUCAS定理的运用+数位DP)

    题面 传送门:UOJ Solution 这题的数位DP好蛋疼啊qwq 好吧,我们说回正题. 首先,我们先回忆一下LUCAS定理: \(C_n^m \equiv C_{n/p}^{m/p} \times ...

  7. BZOJ 3782: 上学路线 [Lucas定理 DP]

    3782: 上学路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 192  Solved: 75[Submit][Status][Discuss] ...

  8. [BZOJ4591][SHOI2015]超能粒子炮·改(Lucas定理+数位DP)

    大组合数取模可以想到Lucas,考虑Lucas的意义,实际上是把数看成P进制计算. 于是问题变成求1~k的所有2333进制数上每一位数的组合数之积. 数位DP,f[i][0/1]表示从高到低第i位,这 ...

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

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

随机推荐

  1. mysql备份 小结 (三种方式的详细解读)

    备份的本质就是将数据集另存一个副本,但是原数据会不停的发生变化,所以利用备份只能回复到数据变化之前的数据.那变化之后的呢?所以制定一个好的备份策略很重要 新建一个all.sqlvim all.sql在 ...

  2. MINI3内存分配算法

    最差适应算法 #ifdef USING_WORST_FIT { //先找到第一个满足要求的空洞, //再以第一个为标准寻找最适合的空洞. //当最适合的空洞完全吻合 //就直接划给它,当空洞较大时就切 ...

  3. iOS开发笔记18:一些编译、开发调试、打包的细节整理

    1.以链库的方式引用第三方库 一些特殊场景可能会要求使用链库的方式使用第三方库,大体设置如下: ①Other Linker Flags里进行设置,格式为-l+库名称 ②Libray Search Pa ...

  4. UOJ#55. 【WC2014】紫荆花之恋

    传送门 暴力思路就是每次点分治计算答案 点分治之后,条件可以变成 \(dis_i-r_i\le r_j-dis_j\) 每次只要查找 \(r_j-dis_j\) 的排名然后插入 \(dis_j-r_j ...

  5. BZOJP1096[ZJOI2007]仓库建设——solution

    Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天, ...

  6. 1739 GPA排序 个人博客:doubleq.win

    个人博客:doubleq.win 1739 GPA排序  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 青铜 Bronze 题解       题目描述 Description ...

  7. 关于echarts绘制树图形的注意事项(文字倾斜、数据更新、缓存重绘问题等)

    最近项目中使用到echarts的树操作,对其中几点注意事项进行下总结. 效果图: 1.基础配置 options的配置如下: { tooltip: { trigger: 'item', triggerO ...

  8. 【Android】17.0 UI开发(八)——利用RecyclerView列表控件实现精美的聊天界面

    1.0 首先新建一个项目,名叫:UIBestPractice,目录如下: 2.0 这里需要先准备两张图片,放在app\src\main\res\drawable-xhdpi目录下. 这里图片名称已经制 ...

  9. 使用react——解决this.props.history.push无法跳转的问题

    转自: https://blog.csdn.net/yingzizizizizizzz/article/details/78751305 场景: 一个组件中,含有ul展开数组的组件,在每一行中,都能点 ...

  10. JavaScript的进阶之路(七)客户端JavaScript知识点总结

    一.客户端JavaScript主要是BOM DOM的操作和js脚本的兼容性.互用性.可访问性.安全性的应用.以及一些框架的引用. 二.BOM:浏览器对象模型 主要介绍window对象 1.定时器:se ...