《算法问题实战策略》-chaper14-整数论
Lucas定理:
在组合计数问题中,我们常面临组合数C(n,m)过大而无法直接计算的困境,那么这里的Lucas定理给出了一个较大组合数进行取余运算的一种递归算法。
什么是Lucas定理?

Lucas定理的推导证明?

这个推导过程基于二项式定理,基于最后的等式,我们通过过找等是左边和右边x^(tp + r)的系数,即可完成对Lucas定理的证明。但是这里并没有呈现对p为什么是素数的说明。
在这里我们给出Lucas定理的另外一种表达形式:

我个人认为,限定了取模的数p是素数,这样统一了运算,即对于∏中每个因子,C(mi,ni) % p的运算,我们都能够结合逆元和费马小定理来进行化简运算。
Lucas定理的编程实现?
通过上图Lucas的定义我们其实已经看到,它是一种递归调用的过程。
然后结合一个题目(Problem source : hdu 3037)来对其进行实现:
Q:给出变量n,m,p,求解x1+x2+x3+…xn = x的解的组数,x∈[0,m]。
分析:首先我们面临不存在空树的情况,利用基本的隔板原理(),容易得到C(m-1,n)组,这显而易见。但是问题的关键在于是允许空树存在的,因此我们需要另外选取空树的数量,即在选取的m-1个元素中再加n个树,在其中选择共选出n-1个空树和隔板,得到C(n+m-1,n-1)即C(n+m-1,m)。
则这道题目的最终解就是∑C(n+m-1,i) = C(n +m,m),i∈[1,m].(二项式系数恒等式,可以参见《具体数学》)
下面是编程实现。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N =;
long long n, m, p, fac[N];
void init()
{
int i;
fac[] =;
for(i =; i <= p; i++)
fac[i] = fac[i-]*i % p;
}
long long pow(long long a, long long b)
{
long long tmp = a % p, ans =;
while(b)
{
if(b & ) ans = ans * tmp % p;
tmp = tmp*tmp % p;
b >>=;
}
return ans;
}
long long C(long long n, long long m)
{
if(m > n) return ;
return fac[n]*pow(fac[m]*fac[n-m], p-) % p;
}
long long Lucas(long long n, long long m) //C(n,m) % p
{
if(m ==) return ;
else return (C(n%p, m%p)*Lucas(n/p, m/p))%p;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%I64d%I64d%I64d", &n, &m, &p);
init(); printf("%I64d\n", Lucas(n+m, m));
}
return ;
}
Ps:这里补充说明一下,上面笔者对于p是素数的必要性的解释过于牵强,证明一开始C(p,f) = 0(mod p)是基于素数才成立的,然后基于此我们才能够完成(1+x)^p = 1 + x^p(mod p)的转化。这样就更加充分解释了Lucas定理p是素数的合理性。
《算法问题实战策略》-chaper14-整数论的更多相关文章
- 算法问题实战策略 PICNIC
下面是另一道搜索题目的解答过程题目是<算法问题实战策略>中的一题oj地址是韩国网站 连接比较慢 https://algospot.com/judge/problem/read/PICNIC ...
- 《算法问题实战策略》-chaper7-穷举法
关于这一章节<算法实战策略>有一段概述问题,我认为对于编程人员来说非常有价值,故在这里进行如下的摘抄: 构想算法是很艰难的工作.相比大家都经历过,面对复杂的要求只是傻乎乎地盯着显示器,或者 ...
- 《算法问题实战策略》-chaper32-网络流
基本的网络流模型: 在图论这一块初步的应用领域中,两个最常见的关注点,其一时图中的路径长度,也就是我们常说的的最短路径问题,另一个则是所谓的“流问题”. 流问题的基本概念: 首先给出一张图. 其实所谓 ...
- 《算法问题实战策略》-chaper13-数值分析
这一章节主要介绍我们在进行数值分析常用的二分.三分和一个近似求解区间积分的辛普森法. 首先介绍二分. 其实二分的思想很好理解并且笔者在之前的一些文章中也有所渗透,对于二次函数甚至单元高次函数的零点求解 ...
- 《算法问题实战策略》——chaper9——动态规划法技巧
Q1: 数字游戏: 两个人(A.B)用n个整数排成的一排棋盘玩游戏,游戏从A开始,每个人有如下操作: (1) 拿走棋盘最右侧或者最左侧的棋子,被拿走的数字从棋盘中抹掉. (2) 棋盘中还剩 ...
- 《算法问题实战策略》-chaper8-动态规划法
Q1:偶尔在电视上看到一些被称为“神童”的孩子们背诵小数点以后几万位的圆周率.背诵这么长的数字,可利用分割数字的方法.我们用这种方法将数字按照位数不等的大小分割后再背诵. 分割形式如下: 所有数字都相 ...
- 《算法问题实战策略》-chaper21-树的实现和遍历
这一章节开始介绍一个数据结构中的一个基本概念——树. 我们从数据结构的解读来解释树结构的重要性,现实世界的数据除了最基本的线性结构(我们常用队列.数组和链表等结构表征),还有一个重要的特性——层级结构 ...
- 算法问题实战策略 QUADTREE
地址 https://algospot.com/judge/problem/read/QUADTREE 将压缩字符串还原后翻转再次压缩的朴素做法 在数据量庞大的情况下是不可取的 所以需要在压缩的情况下 ...
- 算法问题实战策略 DICTIONARY
地址 https://algospot.com/judge/problem/read/DICTIONARY 解法 构造一个26字母的有向图 判断无回路后 就可以输出判断出来的字符序了 比较各个字母的先 ...
随机推荐
- PHPMailer中文说明
PHPMailer中文说明 A开头: $AltBody --属性出自:PHPMailer ::$AltBody文件:class.phpmailer .php说明:该属性的设置是在邮件正文不支持HTML ...
- 提升升级 强制更新 Download
Activity和广播 /** 下载APK细节 1.点击升级后对话框不消失,再次点击时不能重复下载 2.下载过程中退出APP,下次进入应用后要重新下载(因为可能不完整) 3.下载过程中退出APP(或下 ...
- try{...} catch {...} finally{...} 各种情况代码的执行情况
try { int i = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("in the 'try'"); } ca ...
- Android热更新开源项目Tinker集成实践总结
前言 最近项目集成了Tinker,开始认为集成会比较简单,但是在实际操作的过程中还是遇到了一些问题,本文就会介绍在集成过程大家基本会遇到的主要问题. 考虑一:后台的选取 目前后台功能可以通过三种方式实 ...
- JavaScript--数组--sort比较器
因为原装的sort这个API其实是先把要比较的数转换为字符串再进行比较的,所以并不好用 所以准备自定义一个比较器函数: //sort原理--->sort(arr,compare) functio ...
- 34.Spring-Aop.md
http://blog.csdn.net/bigtree_3721/article/details/50759843 目录 [toc] --- 1.概念 1.1概念 AOP是Spring提供的关键特性 ...
- CentOS 6.5下安装MySql 5.7
不管您按下面的方法安装成功否,请留个言,把您遇到的问题写上共勉! 包下载http://url.cn/WrNg5S 环境: 1).软硬件:E6420双核CPU,8G内存,1T硬盘 2).虚拟机下 Cen ...
- 如何使一个你没有源代码的DLL文件变为强命名的DLL
转载: 有时候你会需要一个DLL是强命名的,比如你想把这个文件放到GAC里面.如果这是一个第三方的DLL,你没有源代码,这会是一件比较麻烦的事情.有一个方法可以解决这个问题. 在VS.NET的命名行窗 ...
- HTML5 input控件 placeholder属性
placeholder 属性提供可描述输入字段预期值的提示信息(hint),该提示会在输入字段为空时显示,并会在字段获得焦点时消失. <input placeholder="请输入姓名 ...
- 使用bootstrap模态框实现浮动层
authour: 陈博益 updatetime: 2015-04-22 06:52:15 friendly link: http://v3.bootcss.com/javascript/#modals ...