在开始之前我们先介绍3个定理:

1.乘法逆元

如果ax≡1 (mod p),且gcd(a,p)=1(a与p互质),则称a关于模p的乘法逆元为x。

2.费马小定理:


3.扩展欧几里得

已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式ax + by = gcd(a, b)。

好了,在明白上面的定理后我们开始分析乘法逆元:ax≡1 (mod p) 这个等式用中文描述就是 a乘一个数x并模p等于1,即 a%p*x%p=res,res%p=1;看上去就是同余定理的一个简单等式- -。那么问题来了。

———————————————————————————————————————————–
为什么可以用费马小定理来求逆元呢?

由费马小定理 , 变形得 ,答案已经很明显了:若a,p互质,因为,则,用快速幂可快速求之。

———————————————————————————————————————————–

为什么可以用扩展欧几里得求得逆元?

我们都知道模就是余数,比如12%5=12-5*2=2,18%4=18-4*4=2。(/是程序运算中的除)

那么ax≡1 (mod p)即ax-yp=1.把y写成+的形式就是ax+py=1,为方便理解下面我们把p写成b就是ax+by=1。就表示x是a的模b乘法逆元,y是b的模a乘法逆元。然后就可以用扩展欧几里得求了。

———————————————————————————————————————————–

知道逆元怎么算之后,那么乘法逆元有什么用呢?

先说重点,本人认为!乘法逆元最大的作用就是,在要除以一个数,再取模时,把除法变成乘法运算,然后再取模。因为除法,比如用16/5应该是3.2,但是计算机会算成3.。。误差有没有,用double就更不用说了,数大了一定有误差,所以,有了逆元!!!!

若对于数字A,C 存在X,使A * X = 1 (mod C) ,那么称X为 A 对C的乘法逆元。

逆元的作用?让我们来看下面的例子:
12 / 4 mod 7 = ? 很显然结果是3
我们现在对于数对 (4,7), 可以知道 X = 2是 4 对7的乘法逆元即2*4=1(mod 7)
那么我们有(12 / 4) * (4 * 2 ) = (?) * (1) (mod 7)
除法被完美地转化为了乘法
理论依据:
F / A mod C = ?
如果存在 A*X = 1 (mod C)
那么2边同时乘起来,得到 F * X = ? (mod C)
成立条件
(1) 模方程 A * X = 1(mod C) 存在解
(2) A | F (F % A == 0)
以下来百度百科:
若ax=1 mod f 则称a关于模f的乘法逆元为x。也可表示为ax≡1(mod f)。
当a与f互素时,a关于模f的乘法逆元有唯一解。如果不互素,则无解。如果f为素数,则从1到f-1的任意数都与f互素,即在1到f-1之间都恰好有一个关于模f的乘法逆元。
例如,求5关于模14的乘法逆元:
14=5*2+4
5=4+1
说明5与14互素,存在5关于14的乘法逆元。
1=5-4=5-(14-5*2)=5*3-14
因此,5关于模14的乘法逆元为3。
———————————————————————————————————————————–
接下来进入正题:
Lucas定理针对该取值范围较大又不太大的情况
定理描述


这样将组合数的求解分解为小问题的乘积,下面考虑计算C(ni, mi) %p.

 已知C(n, m) mod p = n!/(m!(n - m)!) mod p。当我们要求(a/b)mod p的值,且b很大,无法直接求得a/b的值时,我们可以转而使用乘法逆元k,将a乘上k再模p,即(a*k) mod p。 其结果与(a/b) mod p等价。
 下面附上Lucas定理的一种证明,见下图,参考冯志刚《初等数论》第37页。
 
 对于该定理的理解,也很好理解:
 其实大可不必看中间一大堆文字描述,直接看下面公式的推导:

  ———————————————————————————————————————————–
  代码实现:
  费马小定理实现(其实跟拓展gcd没多大区别,换了个公式而已)

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include<cstring>using namespace std;typedef long long ll;ll mulit(ll a,ll b,ll m){ll ans=0;while(b){if(b&1) ans=(ans+a)%m;a=(a<<1)%m;b>>=1;}return ans;
}ll quick_mod(ll a,ll b,ll m){ll ans=1;while(b){if(b&1){ans=mulit(ans,a,m);}a=mulit(a,a,m);b>>=1;}return ans;
}ll comp(ll a,ll b,ll m){if(a<b) return 0;if(a==b) return 1;if(b>a-b) b=a-b;ll ans=1,ca=1,cb=1;for(int i=0;i<b;i++){ca=ca*(a-i)%m;cb=cb*(b-i)%m;}ans=ca*quick_mod(cb,m-2,m)%m;return ans;
}ll lucas(ll a,ll b,ll m){ll ans=1;while(a&&b){ans=(ans*comp(a%m,b%m,m))%m;a/=m;b/=m;}return ans;
}int main()
{ll a,b,m;while(cin>>a>>b>>m){cout<<lucas(a,b,m)<<endl;}return 0;
}

拓展gcd实现

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include<cstring>using namespace std;typedef long long ll;ll exgcd(ll a,ll b,ll& x,ll& y){if(a%b==0){x=0,y=1;return b;}ll r,tx,ty;r=exgcd(b,a%b,tx,ty);x=ty;y=tx-a/b*ty;
}ll comp(ll a,ll b,ll m){if(a<b) return 0;if(a==b) return 1;if(b>a-b) b=a-b;ll ans=1,ca=1,cb=1;for(int i=0;i<b;i++){ca=ca*(a-i)%m;cb=cb*(b-i)%m;}ll x,y;exgcd(cb,m,x,y);x=(x%m+m)%m;ans=ca*x%m;return ans;
}ll lucas(ll a,ll b,ll m){ll ans=1;while(a&&b){ans=(ans*comp(a%m,b%m,m))%m;a/=m;b/=m;}return ans;
}int main()
{ll a,b,m;int n;cin>>n;while(n--){cin>>a>>b>>m;cout<<lucas(a+b,b,m)<<endl;}return 0;
}

试试拓展吧
拓展卢卡斯定理

卢卡斯定理(十分钟带你看懂)相关推荐

  1. 十分钟带你看懂Netty如何实现C-S,太香了

    一.码场心得 你是个能吃苦的人吗? 从前的能吃苦大多指的体力劳动的苦,但现在的能吃苦已经包括太多维度,包括:读书学习&寂寞的苦.深度思考&脑力的苦.自律习惯&修行的苦.自控能力 ...

  2. 一分钟带你看懂UML图

    一分钟带你看懂UML图 小小demo package Test;/*** @Description:* @ProjectNmae: demo1* @PackageName: Test* @ClassN ...

  3. 三分钟带你看懂prototype原型——ES6进阶

    三分钟带你看懂prototype原型--ES6进阶 1. prototype 定义 2. new 构造函数 3. 存储 4. prototype 作用 1. prototype 定义 在JS中的类的实 ...

  4. 三分钟带你看懂HDMI接口的PCB设计

    三分钟带你看懂HDMI接口的PCB设计 本文主要讲解的是HDMI的设计,包括作用和运用的总结,希望大家看了以后能轻松的应对各种HDMI方案的PCB设计. 一.什么是HDMI? 高清晰度多媒体接口(英文 ...

  5. 【 全干货 】5 分钟带你看懂 Docker !

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者丨唐文广:腾讯工程师,负责无线研发部地图测试. 导语:Docker,近两年才流行起来的超轻量级虚拟机,它可以让你轻松完成持续集成.自动交付 ...

  6. 【 全干货 】5 分钟带你看懂 Docker ! 1

    作者丨唐文广:腾讯工程师,负责无线研发部地图测试. 导语:Docker,近两年才流行起来的超轻量级虚拟机,它可以让你轻松完成持续集成.自动交付.自动部署,并且实现开发环境.测试环境.运维环境三方环境的 ...

  7. 【全干货】5分钟带你看懂 Docker!

    作者丨唐文广:腾讯工程师,负责无线研发部地图测试. 导语:Docker,近两年才流行起来的超轻量级虚拟机,它可以让你轻松完成持续集成.自动交付.自动部署,并且实现开发环境.测试环境.运维环境三方环境的 ...

  8. 十分钟让你看懂「共享经济」到底是什么?

    公司组织了一次分享活动,我被分到了共享经济的主题.于是翻箱倒柜两天去了解这个最近很火的概念.觉得只稍懂了皮毛,之后继续去学习吧,这次分享也只能算是1.0(笑).今天给大家分享的主题是共享经济,人人分享 ...

  9. rocketmq广播消息为什么不能重试_几分钟带你看懂“消息队列和RocketMQ”的入门总结

    消息队列扫盲 消息队列顾名思义就是存放消息的队列,队列我就不解释了,别告诉我你连队列都不知道似啥吧? 所以问题并不是消息队列是什么,而是 消息队列为什么会出现?消息队列能用来干什么?用它来干这些事会带 ...

最新文章

  1. SUN 论坛http://forums.sun.com/forum.jspa?forumID=840
  2. 虚拟化何以四两拨千斤
  3. 【NOI2018】你的名字【后缀自动机】【可持久化线段树合并】【乱搞】
  4. 安装ps时无法验证订阅状态_免费申请office E5开发者订阅,附无限续期+私人网盘教程...
  5. 深入理解jQuery中的Deferred
  6. 【转】XP下OpenProcess( PROCESS_ALL_ACCESS...失败
  7. 内存记号(Memory Trail)[自定义的名字] --调试方法
  8. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第2节 Stream流式思想概述_1_使用传统的方式,遍历集合,对集合进行过滤...
  9. 关于vivo手机调试安装“解析程序包时出现问题”的解决方案
  10. 用HTml+csss实现优惠券
  11. 注册gitlab-runner
  12. Visual SourceSafe中的权限管理(转载,已测试)
  13. 日常渗透刷洞的一些小工具
  14. java defunct_神奇的僵尸进程问题
  15. 2014年3月CCF软考试题
  16. 用python画小仓鼠教程_看看萌萌哒的仓鼠是怎么画出来的,最详细的图文教程,别错过!...
  17. 基于Qt5 的串口助手开发
  18. VS开发工具的常用插件
  19. eclipse打不开的问题
  20. Java实现寻找二维数组的鞍点

热门文章

  1. 容器监控工具heapster与Prometheus的简要分析
  2. Spring Boot 远程调试
  3. python plot label改字体_python – 如何在matplotlib图中更改xticks字体大小
  4. 百度语音助手电脑版 v3.0 官方版
  5. 设置多行省略号-webkit-line-clamp
  6. 浅谈web前端三大主流框架
  7. oracle ora-00911
  8. win11解决IE浏览器使用问题
  9. 在JSTL 中使用小型数据库 SQLite
  10. intellij idea的Browse repositories无法搜索安装插件?