逆元求组合数

article/2025/9/23 18:30:32

逆元简介

同余符号 ≡
先bb一下 ≡,这个符号有三个意思,再这里用到的意思为“同余符号”。≡ 的介绍
两个整数a,b,若它们除以整数m所得的余数相等,则称a,b对于模m同余
记作a≡b(mod m)
读作a同余于b模m,或读作a与b关于模m同余。
比如26≡14(mod 12)。
什么是逆元
如果一个线性同余方程 ax ≡ 1(mod b) ,则 x 称为 a mod b 的逆元.
逆元的含义
模b意义下,1个数a如果有逆元x,那么除以a相当于乘以x。
也就是(a/b)%p=(ax)%p=(a%p)(b%p)%p

那么问题来了,这逆元有啥用吗,这个问题问的好啊
如果我们要求一个组合数C(n,m)%p=(n!/(n-m)!*m!)%p,但是取模的性质对于除法不适用啊。
在这里插入图片描述
但当这个n和m很大时又不得不取模,不取模就会溢出。所以就可以用逆元来把乘法代替除法。

怎么求逆元

暴力O( P)求逆元
先举这个最简单最暴力的方法,这样便于理解逆元。具体思路就是枚举1~p-1,检查是否有符合条件的a*x=1(mod p)。时间复杂度为O(P)。

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{int a,p;cin>>a>>p;for(int x=1;x<p;x++){if(x*a%p==1) {printf("%d\n",x);break;}}return 0;
}

扩展欧几里得法
给定模数p,求a的逆元相当于求解ax=1(mod p)
这个方程可以转化为ax-py=1
然后套用求二元一次方程的方法,用扩展欧几里得算法求得一组x0,y0和gcd (最大公约)
检查gcd是否为1
gcd不为1则说明逆元不存在 ,若为1,则把x0调整到0~m-1的范围中即可
( ①:extgcd 目的 求 x ,y ; ②:逆元 目的 求 x )
一个数有逆元的充分必要条件是gcd(a,n)=1,如果gcd(a,n)>1,则不存在逆元

int exgcd(int a,int b,int &x,int &y)
{if(b==0) {x=1,y=0;return a;}int r = exgcd(b,a%b,x,y);int t = x;x = y;y = t - a/b*y;return r;
}

快速幂法

这个要运用 费马小定理 :
在这里插入图片描述
再看看推导过程:
在这里插入图片描述
由以上推导就可以通过求一个幂运算很简单的求出逆元辽。

上一个代码,具体功能就是求n和m的组合数mod1e9+7

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const ll Mod=1e9 + 7;
ll fac[100010];//存阶乘 
ll inv[100010];//存逆元 ll quick(ll a,int b)//快速幂算法 
{ll ans=1;while(b){if(b&1)ans=(ans*a)%Mod;a=a*a%Mod;b>>=1;}return ans;
}void getfac()
{fac[0]=inv[0]=1;for(int i=1;i<=100000;i++){fac[i]=fac[i-1]*i%Mod;inv[i]=quick(fac[i],Mod-2); }
}ll getans(ll n,ll m)
{return fac[n]*inv[n-m]%Mod*inv[m]%Mod;
}int main()
{getfac();//初始化ll n,m;while(cin>>n>>m){ll ans=getans(n,m);cout<<ans<<endl;} 
}

Lucas定理

对于大组合数取模,n,m不大于10 ^ 5的话,用逆元的方法,可以解决。对于n,m大于10 ^ 5的话,那么要求p<10 ^ 5,这样就是Lucas定理了,将n,m转化到10^5以内解。
Lucas定理是用来求 c(n,m) mod p,p为素数的值。
C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p
也就是Lucas(n,m)%p=Lucas(n/p,m/p)*C(n%p,m%p)%p
求上式的时候,Lucas递归出口为m=0时返回1,原因是因为Lucas(a,0,q)=1;
模板:

#include <cstdio>  
#include <iostream>  
#include <cmath>  
#include <cstring>  
#include <algorithm>  
using namespace std;  
#define maxn 100010  
typedef long long LL;  
LL m,n,p;  
LL Pow(LL a,LL b,LL mod)  
{  LL ans=1;  while(b)  {  if(b&1)ans=(ans*a)%mod;a=a*a%mod;b>>=1;}  return ans;  
}  
LL C(LL n,LL m)  
{  if(n<m)  return 0;  LL ans=1;  for(int i=1;i<=m;i++)  {  ans=ans*(((n-m+i)%p)*Pow(i,p-2,p)%p)%p;  }  return ans;  
}  
LL Lucas(LL n,LL m)  
{  if(m==0)  return 1;  return (Lucas(n/p,m/p)*C(n%p,m%p))%p;  
}  
int main()  
{  int t;  scanf("%d",&t);  while(t--)  {  scanf("%lld%lld%lld",&n,&m,&p);  printf("%lld\n",Lucas(n,m));  }  return 0;  
} 

http://chatgpt.dhexx.cn/article/Y58fj3M3.shtml

相关文章

组合数(Combinatorial_Number)

定义&#xff1a; 从n个不同元素中&#xff0c;任取m(m≤n)个元素并成一组&#xff0c;叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数&#xff0c;叫做从n个不同元素中取出m个元素的组合数。 公式&#xff1a; 在线性写法中被…

组合数的计算

本篇博客来自南昌理工学院acm集训队成员yyj 组合数 1.定义 组合数&#xff1a;从 n 个不同元素中每次取出 m 个不同元素 &#xff0c;不管其顺序合成一组&#xff0c;称为从 n 个元素中不重复地选取 m 个元素的一个组合。所有这样的组合的种数称为组合数。 2.性质与描述 2…

组合数的性质证明

性质 极其简单的证明 根据杨辉三角的性质&#xff0c;第x行第y个的值为C(x-1,y-1) 那么 一目了然。 严肃的证明

组合数性质--二项式系数之和等于2^n的证明

1.公式 首先我们都知道组合数的意义&#xff0c;就是说一共有n个样本&#xff0c;一次性从中取出m个样本&#xff0c;一共有多少种不同的取法。它的公式如下&#xff1a; 它有这么一个性质&#xff1a; 该性质有若干种证明方式&#xff0c;今天我在这边写出我觉得挺巧妙的一种…

组合数原理

资料来源&#xff1a;https://baike.baidu.com/ 组合数 从n个不同元素中&#xff0c;任取m(m≤n)个元素并成一组&#xff0c;叫做从n个不同元素中取出m个元素的一个组合&#xff1b;从n个不同元素中取出m(m≤n)个元素的所有组合的个数&#xff0c;叫做从n个不同元素中取出m个…

深入详细理解矩阵 (矩阵的加减乘、转置、共轭、共轭转置)

简介 矩阵:英文名Matrix。在数学名词中&#xff0c;矩阵用来表示统计数据等方面的各种有关联的数据。这个定义很好地解释了Matrix代码制造世界的数学逻辑基础。矩阵是数学中最重要的基本概念之一&#xff0c;是代数学的一个主要研究对象&#xff0c;也是数学研究及应用的一个重…

【线性代数之二】矩阵与行列式

一、矩阵 1.1 定义 由 m n 个数aij排成的m行n列的数表称为m行n列的矩阵&#xff0c;简称m n矩阵。记作&#xff1a; 这mn 个数称为矩阵A的元素&#xff0c;简称为元&#xff0c;数aij位于矩阵A的第i行第j列&#xff0c;称为矩阵A的(i,j)元&#xff0c;以数 aij为(i,j)元的…

CString类型转换为LPCSTR类型

今天编程遇到一个问题&#xff0c;就是openGL中某个函数需要传入LPCSTR类型的参数&#xff0c;而通过MFC对话框获取得到的是CString类型的参数&#xff0c;因此需要将CString转化为LPCSTR类型&#xff0c;网上有很多这样的强转类型&#xff0c;然而却发现在强转的时候没有用&am…

linux jstat 简介

本文目录一览&#xff1a; 1、Linux使用jstat命令查看jvm的GC情况2、linux怎么监控 jvm内存 jstat3、Linux系统监控要用到哪些命令4、linux上如何安装jstatd服务 Linux使用jstat命令查看jvm的GC情况 Linux 使用jstat命令查看jvm的GC情况 命令格式 jstat命令命令格式&#…

内存屏障与volatile(C语言版)

内存屏障与volatile&#xff08;C语言版&#xff09; 最有价值的写在最前面 内存屏障与volatile是高并发编程中比较常用的两个技术&#xff0c;无锁队列的时候就会用到这两项技术。然而这两项技术设计比较广的基础知识&#xff0c;所以比较难以理解&#xff0c;也比较不容易解…

WDM驱动

WDM英文Windows Driver Model(WDM)的缩写。 简介 WDM WDM是WINDOWS2000认证的驱动程序&#xff0c;WIN2000由NT发展而来&#xff0c;所以对于设备的支持功能有限&#xff0c;同时为了最大限度的保障稳定性&#xff0c;所以推崇WDM驱动&#xff0c;但同时WDM驱动也就是功能最少…

快速转换dBm与W

dBm是一个表示功率绝对值的值&#xff08;也可以认为是以1mW功率为基准的一个比值&#xff09;&#xff0c;计算公式为&#xff1a;10log&#xff08;功率值/1mw&#xff09;。 这里我们介绍一种将dBm转换为W的口算方法&#xff0c;这一方法总结起来就是 “1个基准”和“2个原则…

学内核之十一:ARM64屏障指令使用指南

关于屏障指令&#xff0c;主要是与乱序有关。特别是在内核开发中&#xff0c;这是一个非常重要的主题。屏障由乱序引起&#xff0c;乱序则是由优化引起。 自从摩尔定律不断被逼近极限&#xff0c;半导体的优化不再单纯通过提升频率来实现。多核心、并发执行变成了主流的优化思路…

WTM

WTM的由来 WalkingTec.Mvvm框架&#xff08;简称WTM&#xff09;最早开发与2013年&#xff0c;基于Asp.net MVC3 和 最早的Entity Framework, 当初主要是为了解决公司内部开发效率低&#xff0c;代码风格不统一的问题。经历了四年间数十个项目的考验&#xff0c;框架逐步的完善…

WMIC使用

目录 WMI 远程创建进程 wmiexec wmiexec.py wmiexec.vbs Invoke-WmiCommand.ps1 Invoke-WMIMethod WMI WMI全称“windows管理规范”&#xff0c;是一个windows服务。从win2003开始一直存在。它原本的作用是方便管理员对windows主机进行管理。因此在内网渗透中&#xff…

Arm64内存屏障

一、内存类型 ARMv8架构将系统中所有的内存&#xff0c;按照它们的特性&#xff0c;划分成两种&#xff0c;即普通内存和设备内存。并且它们是互斥的&#xff0c;也就是说系统中的某段内存要么是普通内存&#xff0c;要么是设备内存&#xff0c;不能都是。 1&#xff09;普通…

barrier(wmb,mb,rmb)和cache coherence

http://www.linuxforum.net/forum/gshowflat.php?Cat&BoardlinuxK&Number428239&page5&viewcollapsed&sb5&oall&fpart 注: 这里的barrier 指的是wmb, rmb, mb. 一 直找不到合适的资料说明barrier和 Cache coherence 之间的关系. 在<<ldd>…

mw与dbm换算

1. 基本概念 dbm&#xff1a;意即分贝毫X&#xff0c;可以表示分贝毫伏&#xff0c;或者分贝毫瓦。他是一个表示功率绝对值的单位。 功率/电平&#xff08;dBm&#xff09;&#xff1a;放大器的输出能力&#xff0c;一般单位为w、mw、dBm。dBm是取1mw作基准值&#xff0c;以分贝…