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-整数论的更多相关文章

  1. 算法问题实战策略 PICNIC

    下面是另一道搜索题目的解答过程题目是<算法问题实战策略>中的一题oj地址是韩国网站 连接比较慢 https://algospot.com/judge/problem/read/PICNIC ...

  2. 《算法问题实战策略》-chaper7-穷举法

    关于这一章节<算法实战策略>有一段概述问题,我认为对于编程人员来说非常有价值,故在这里进行如下的摘抄: 构想算法是很艰难的工作.相比大家都经历过,面对复杂的要求只是傻乎乎地盯着显示器,或者 ...

  3. 《算法问题实战策略》-chaper32-网络流

    基本的网络流模型: 在图论这一块初步的应用领域中,两个最常见的关注点,其一时图中的路径长度,也就是我们常说的的最短路径问题,另一个则是所谓的“流问题”. 流问题的基本概念: 首先给出一张图. 其实所谓 ...

  4. 《算法问题实战策略》-chaper13-数值分析

    这一章节主要介绍我们在进行数值分析常用的二分.三分和一个近似求解区间积分的辛普森法. 首先介绍二分. 其实二分的思想很好理解并且笔者在之前的一些文章中也有所渗透,对于二次函数甚至单元高次函数的零点求解 ...

  5. 《算法问题实战策略》——chaper9——动态规划法技巧

    Q1: 数字游戏: 两个人(A.B)用n个整数排成的一排棋盘玩游戏,游戏从A开始,每个人有如下操作: (1)    拿走棋盘最右侧或者最左侧的棋子,被拿走的数字从棋盘中抹掉. (2)    棋盘中还剩 ...

  6. 《算法问题实战策略》-chaper8-动态规划法

    Q1:偶尔在电视上看到一些被称为“神童”的孩子们背诵小数点以后几万位的圆周率.背诵这么长的数字,可利用分割数字的方法.我们用这种方法将数字按照位数不等的大小分割后再背诵. 分割形式如下: 所有数字都相 ...

  7. 《算法问题实战策略》-chaper21-树的实现和遍历

    这一章节开始介绍一个数据结构中的一个基本概念——树. 我们从数据结构的解读来解释树结构的重要性,现实世界的数据除了最基本的线性结构(我们常用队列.数组和链表等结构表征),还有一个重要的特性——层级结构 ...

  8. 算法问题实战策略 QUADTREE

    地址 https://algospot.com/judge/problem/read/QUADTREE 将压缩字符串还原后翻转再次压缩的朴素做法 在数据量庞大的情况下是不可取的 所以需要在压缩的情况下 ...

  9. 算法问题实战策略 DICTIONARY

    地址 https://algospot.com/judge/problem/read/DICTIONARY 解法 构造一个26字母的有向图 判断无回路后 就可以输出判断出来的字符序了 比较各个字母的先 ...

随机推荐

  1. Android(java)学习笔记231:服务(service)之混合方式开启服务

    1. 前面我们已经讲过可以使用两种方式开启服务 startService----stopService:        oncreate() ---> onstartCommand() ---& ...

  2. poj 2679 Adventurous Driving(SPFA 负环)

    /* - - 这题做了一天.....粗心害死人啊 题目描述恶心 数据更恶心... 先处理一下能走的边 能走的点(到这建边从终点跑一下.) 然后就是SPFA了 注意负环的判断 */ #include&l ...

  3. Word复制和替换实例

    public string Path { get { DirectoryInfo info = new DirectoryInfo(Application.StartupPath); return i ...

  4. Smarty环境配置

    Smaty优点:1.代码分离 2.缓存技术 使用步骤: 1.下载Smaty模板 2.将模板中那个lib文件夹复制到项目中(一般为根目录,并且重命名在此命名为Smarty), 3.配置PHP 1.新建一 ...

  5. 重新开始学习javase_隐藏实施过程

    一.隐藏实施过程 对于隐藏实施过程,thinking in java中讲了很好,无非就是一个好的程序尽量做到,对外公开的程序,即使内部程序发生变动,也不会影响这些公开的服务的使用 类的导入java中的 ...

  6. python challenge 16

    前情回顾:上一篇 第16关地址 打开16关,又是一张奇奇怪怪很多点点的图片,应该又是与PIL库有关的. 页面的标题是:let me get this straight.这是英语中的一句俚语,意思是让我 ...

  7. linux ulimit的使用,如何产生core文件,调试段错误

    ---恢复内容开始--- 下面先简单介绍下ulimit命令: 1. limit -a 可以查看系统各种资源的限制,如: core文件大小,数据段的大小等. $ ulimit -a core file ...

  8. Maven 安装记

    java初学者 昨天通m2e插件把maven项目导入eclipse的时候各种bug,看了各家技术博客,决定安装maven好好了解下. 安装maven也是一波三折的,先是看各种安装指导,结果环境变量都没 ...

  9. [javascript]js修改title

    使用javascript修改title 1.这个在chrome中可以成功,在ie8中报错 <!DOCTYPE html> <html> <head> <tit ...

  10. Delphi-LowerCase 函数

    函数名称 LowerCase 所在单元 System.SysUtils 函数原型 function LowerCase(const S: string): string; 函数功能 将字符串中所有的大 ...