组合数取模方法总结(Lucas定理介绍)
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定理介绍)的更多相关文章
- 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 ...
- 组合数取模介绍----Lucas定理介绍
转载https://www.cnblogs.com/fzl194/p/9095177.html 组合数取模方法总结(Lucas定理介绍) 1.当n,m都很小的时候可以利用杨辉三角直接求. C(n,m) ...
- CF451E Devu and Flowers (隔板法 容斥原理 Lucas定理 求逆元)
Codeforces Round #258 (Div. 2) Devu and Flowers E. Devu and Flowers time limit per test 4 seconds me ...
- 【Gym 100947E】Qwerty78 Trip(组合数取模/费马小定理)
从(1,1)到(n,m),每次向右或向下走一步,,不能经过(x,y),求走的方案数取模.可以经过(x,y)则相当于m+n步里面选n步必须向下走,方案数为 C((m−1)+(n−1),n−1) 再考虑其 ...
- Codeforces 57C (1-n递增方案数,组合数取模,lucas)
这个题相当于求从1-n的递增方案数,为C(2*n-1,n); 取模要用lucas定理,附上代码: #include<bits/stdc++.h> using namespace std; ...
- [UOJ 275/BZOJ4737] 【清华集训2016】组合数问题 (LUCAS定理的运用+数位DP)
题面 传送门:UOJ Solution 这题的数位DP好蛋疼啊qwq 好吧,我们说回正题. 首先,我们先回忆一下LUCAS定理: \(C_n^m \equiv C_{n/p}^{m/p} \times ...
- BZOJ 3782: 上学路线 [Lucas定理 DP]
3782: 上学路线 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 192 Solved: 75[Submit][Status][Discuss] ...
- [BZOJ4591][SHOI2015]超能粒子炮·改(Lucas定理+数位DP)
大组合数取模可以想到Lucas,考虑Lucas的意义,实际上是把数看成P进制计算. 于是问题变成求1~k的所有2333进制数上每一位数的组合数之积. 数位DP,f[i][0/1]表示从高到低第i位,这 ...
- 组合数取模&&Lucas定理题集
题集链接: https://cn.vjudge.net/contest/231988 解题之前请先了解组合数取模和Lucas定理 A : FZU-2020 输出组合数C(n, m) mod p (1 ...
随机推荐
- iOS开源项目周报0323
由OpenDigg 出品的iOS开源项目周报第十三期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等. CHIPag ...
- C# 视频转换类
using System.Web; using System.Configuration; namespace DotNet.Utilities { public class VideoConvert ...
- 使用http维持socket长连接
项目中有遇到问题如下: 1.旧版的cs服务,因为每个用户和唯一的长连接是在登录后绑定的,并且所有的消息报文均是基于该长连接去发送接收的,所以要求node服务要维持一个长连接,然后根据该用户获取长连接, ...
- git merge后,后悔了如何回退
今天将feature分支的代码merge到develop分支后我后悔了,因为feature分支的功能还没有全部开发完成,我在feature分支上commit是可以的,但是这之后我又把它merge到了d ...
- [linux] C语言Linux系统编程-socket回声客户端
回声客户端: 1.所谓“回声”,是指客户端向服务器发送一条数据,服务器再将数据原样返回给客户端,就像声音一样,遇到障碍物会被“反弹回来”. 2.客户端也可以使用 write() / send() 函数 ...
- [javaSE] GUI(jar包双击运行)
首先应该在java文件中定义包名,package 包名 带包编译成class文件 切换到目录下,使用jar -cvf xx.jar 包名,就是把那个包放到xx.jar包里面 此时双击会报错,找不到要执 ...
- oracle sum(col1) over(partition by col2 order by col3):实现分组递增汇总
应公司业务要求,需要对数据进行分组汇总做辅助列进行查询 所以使用到了sum(col1) over(partition by col2 order by col3)函数,为了学习与提高在此进行记录. 1 ...
- OpenStack IceHouse 部署 - 4 - 计算节点部署
Nova计算服务(计算节点) 参考 本页内容依照官方安装文档进行,具体参见Configure a compute node(nova service) 前置工作 数据库 由于我们在Nova(计算管理 ...
- Django实现数据库中表格的增删查改
1.urls.py """Django_demo1 URL Configuration The `urlpatterns` list routes URLs to vie ...
- 牛客Wannafly挑战赛23F 计数(循环卷积+拉格朗日插值/单位根反演)
传送门 直接的想法就是设 \(x^k\) 为边权,矩阵树定理一波后取出 \(x^{nk}\) 的系数即可 也就是求出模 \(x^k\) 意义下的循环卷积的常数项 考虑插值出最后多项式,类比 \(DFT ...