《算法问题实战策略》-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字母的有向图 判断无回路后 就可以输出判断出来的字符序了 比较各个字母的先 ...
随机推荐
- 异步tcp通信——APM.Server 消息推送服务的实现
消息推送服务 服务器推送目前流行就是私信.发布/订阅等模式,基本上都是基于会话映射,消息对列等技术实现的:高性能.分布式可以如下解决:会话映射可采用redis cluster等技术实现,消息对列可使用 ...
- 洛谷比赛 Joe的数
/* 开始暴力+滚动数组70 后来发现不用循环很多 找p的倍数 找%p意义下为0的就好了 */ #include<iostream> #include<cstdio> #inc ...
- jQuery的live()方法对hover事件的处理示例
hover([over,]out) 一个模仿悬停事件(鼠标移动到一个对象上面及移出这个对象)的方法 当鼠标移动到一个匹配的元素上面时,会触发指定的第一个函数. 当鼠标移出这个元素时,会触发指定的第二个 ...
- My.Ioc 的性能
IoC/DI 这个概念,最初是由 Martin Fowler 提出来的.之后,很快在 Java 社区大行其道.在 .net 社区,IoC 的流行要比 Java 晚一些.尽管如此,现在开源社区中也已经出 ...
- (转)PHP中的ob_start用法详解
用PHP的ob_start();控制您的浏览器cache Output Control 函数可以让你自由控制脚本中数据的输出.它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况.输出 ...
- PAT-1041 Be Unique
Being unique is so important to people on Mars that even their lottery is designed in a unique way. ...
- java判断网络连接是否正常
/** * 判断本机当前的网络状态是否联通 * 在这里主要用到中国天气信息,所以访问百度地址是否能够访问成功来判断当前的网络状态 */ public static boolean isConnect( ...
- asp.net Server.HtmlEncode和HtmlDecode
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server">< ...
- javescript扩展方法
<script type="text/javascript"> //扩展方法 '原型'->'prototype' //通过类对像的prototype设置扩展方法 ...
- iOS开发——常用宏的定义
有些时候,我们需要将代码简洁化,这样便于读代码.我们可以将一些不变的东东抽取出来,将变化的东西作为参数.定义为宏,这样在写的时候就简单多了. 下面例举了一些常用的宏定义和大家分享: 1. 判断设备的操 ...