【转】Lucas定理 & 逆元学习小结
(From:离殇灬孤狼)
这个Lucas定理是解决组合数的时候用的,当然是比较大的组合数了。比如C(1000000,50000)% mod,这个mod肯定是要取的,要不算出来真的是天文数字了。
对于一个组合数C(n,k),它等于 n! / ( k! * ( n - k)! ) 我们要求一个mod。但是我们知道的同余定理是在 + - * 这三个运算中使用的,对于除法我们不能轻易的使用同余定理。如果我们能把除数(分母)转化为一个乘法就好了,这个时候我们就用到了逆元的知识:
这就开始说逆元了:
定义:对于正整数和
,如果有
,那么把这个同余方程中
的最小正整数解叫做
模
的逆元。
如果m是素数且GCD(a,mod)== 1,我们就直接可以用费马小定理求了。即求:a^(m-2)% mod。
用快速幂求即可。
如果还不明白逆元是个啥,我举个简单的例子来看看:
求:(24 / 3)% 5 我们可以直接观察得结果:3
但是这个只是个24,如果前面是一个很大很大的数的连乘longlong都存不下呢?我们肯定是一边乘一边求mod。在这里,我们把24对5求模,结果是4。这个4不能直接除以3再求模,一看肯定是错误的。这里我们要把这个4乘3的逆元再求模。根据刚刚说的,3的逆元为3^(5-2) = 27 (或者用扩展欧几里得exGCD(3,5,x,y)这样求出来的x就是3mod5的逆元)。然后按照刚刚说的,4 * 27 % 5 = 3 ,这就是结果了。
反正根据我的理解就是,由于除法不能使用同余定理,那么我们就把除以的这个数转化为乘法,然后用同余定理即可。
逆元如果知道了,我们继续说Lucas定理的使用。
先说一下定义:
Lucas 定理:A、B是非负整数,p是质数。AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0] 这里的每一个数组元素表示其p进制的每一位。
则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0])。也就是说,把大组合数问题变成了一个个的小组合数。(A,B小于mod)
对于每一个小组合数,我们继续刚才的说明:n! / ( k! * ( n - k)! ) ,我们要求k!*(n - k)!的逆元。套用上面逆元的求法,再看一下下面的模板,应该就不难理解了。
Lucas定理用递归的方法,代码:
LL Lucas(LL n,LL k) //Lucas定理递归
{
if (k == ) //递归终止条件
return ;
else
return C(n % mod , k % mod) * Lucas(n / mod , k / mod) % mod;
}
然后我们要求组合数,代码:
这里用到了快速幂,代码:
LL quick_mod(LL n , LL m) //求快速幂
{
LL ans = ;
n %= mod;
while (m)
{
if (m & )
ans = ans * n % mod;
n = n * n % mod;
m >>= ;
}
return ans;
}
对于阶乘,我们可以先打一个表,运算就快很多:
void getfac() //打一个阶乘表
{
for (int i = ; i <= ; i++)
fac[i] = fac[i-] * i % mod;
}
来一个大代码:(求大组合数对mod = 1000003求模)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
LL mod = ;
LL fac[+] = {,};
void getfac() //打一个阶乘表
{
for (int i = ; i <= ; i++)
fac[i] = fac[i-] * i % mod;
}
LL quick_mod(LL n , LL m) //求快速幂
{
LL ans = ;
n %= mod;
while (m)
{
if (m & )
ans = ans * n % mod;
n = n * n % mod;
m >>= ;
}
return ans;
}
LL C(LL n , LL k) //费马小定理求逆元
{
if (k > n)
return ;
else
return fac[n] * (quick_mod(fac[k] * fac[n-k] % mod , mod - )) % mod;
}
LL Lucas(LL n,LL k) //Lucas定理递归
{
if (k == ) //递归终止条件
return ;
else
return C(n % mod , k % mod) * Lucas(n / mod , k / mod) % mod;
}
int main()
{
getfac();
LL n,k;
int Case = ;
int u;
scanf ("%d",&u);
while (u--)
{
scanf ("%lld %lld",&n,&k);
printf ("Case %d: %lld\n",Case++,Lucas(n,k));
}
return ;
}
http://blog.csdn.net/clove_unique/article/details/54571216
【转】Lucas定理 & 逆元学习小结的更多相关文章
- [Lucas定理]【学习笔记】
Lucas定理 [原文]2017-02-14 [update]2017-03-28 Lucas定理 计算组合数取模,适用于n很大p较小的时候,可以将计算简化到小于p $ \binom{n}{m} \m ...
- lucas定理 +证明 学习笔记
lucas定理 p为素数 \[\dbinom n m\equiv\dbinom {n\%p} {m\%p} \dbinom {n/p}{m/p}(mod p)\] 左边一项直接求,右边可递归处理,不包 ...
- CF451E Devu and Flowers (隔板法 容斥原理 Lucas定理 求逆元)
Codeforces Round #258 (Div. 2) Devu and Flowers E. Devu and Flowers time limit per test 4 seconds me ...
- HDU3037 Saving Beans(Lucas定理+乘法逆元)
题目大概问小于等于m个的物品放到n个地方有几种方法. 即解这个n元一次方程的非负整数解的个数$x_1+x_2+x_3+\dots+x_n=y$,其中0<=y<=m. 这个方程的非负整数解个 ...
- lucas 定理学习
大致意思就是求组合数C(n , m) % p的值, p为一个偶数 可以将组合数的n 和 m都理解为 p 进制的表示 n = ak*p^k + a(k-1)*p^(k-1) + ... + a1*p ...
- 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其次,我们 ...
- 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其次,我们 ...
- [模板] 数学基础:快速幂/乘/逆元/exGCD/(ex)CRT/(ex)Lucas定理
方便复制 快速乘/幂 时间复杂度 \(O(\log n)\). ll nmod; //快速乘 ll qmul(ll a,ll b){ ll l=a*(b>>hb)%nmod*(1ll< ...
- Lucas定理学习笔记
从这里开始 一个有趣的问题 扩展Lucas算法 一个有趣的问题 题目大意 给定$n, m, p$,求$C_{n}^{m}$除以$p$后的余数. Subtask#1 $0\leqslant m\leq ...
随机推荐
- Office Web Apps 2013对文档的精细定位
在一般情况下,我们使用Office Web Apps查看文档都是从第一页开始查看,不过在SharePoint搜索中,我们看到这样的结果: 这是2013搜索的一个新特性,可以深入定位到文档内部,支持PP ...
- Python小练习(持续更新....)
最近一直在学习python,这些小练习有些是书上的,有些是别人博客上的! # 1.题目1# 给一个字符串,统计其中的数字.字母和其他类型字符的个数:# 比如输入“124mid-=”,输出:数字=3,字 ...
- Webpack探索【2】--- 安装、项目初始化、webpack.config.js配置文件
本文主要讲安装.项目初始化.webpack.config.js配置文件方面的内容.
- 我的Java开发学习之旅------>Java 格式化类(java.util.Formatter)基本用法
本文参考: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html http://www.blogjava.net/ ...
- Linux安装过程记录信息
全新的linux安装完成后,会在root目录下有一下三个文件,记录了Linux的安装细节 anaconda-ks.cfg 以Kickstart配置文件的格式记录安装过程中设置的选项信息 install ...
- socket编程python+c
python版: server: def socket_loop_server_function(): HOST = '192.168.56.1' PORT = 21567 sk = socket.s ...
- linux c编程:线程创建
前面章节中介绍了进程.从这一章开始介绍线程.进程和线程的差别是什么呢: 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实 ...
- ABAP动态生成经典应用之Dynamic SQL Excute 程序
[转自http://blog.csdn.net/mysingle/article/details/678598]开发说明:在SAP的系统维护过程中,有时我们需要修改一些Table中的数据,可是很多Ta ...
- error in static/js/xxx.js from UglifyJs Unpected token: punc() [static/js/xxx.js]
出现问题 使用vue+element-ui+webpack开发项目时,Jenkins构建出现报错error in static/js/xxx.js from UglifyJs Unpected tok ...
- 在Nginx中做负载均衡配置的实例讲解
负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法. 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可以解释N台服务器平均分担负载,不会因为某 ...