Lucas
卢卡斯定理/Lucas 定理:
Lucas 定理用于求解大组合数取模的问题,其中模数必须为素数。正常的组合数运算可以通过递推公式求解,但当问题规模很大,而模数是一个不大的质数的时候,就不能简单地通过递推求解来得到答案,需要用到 Lucas 定理。
对于质数
对于第二部分可以直接求组合数,对于第一部分可以继续递归
单次时间复杂度
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
ll s=0,k=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c=='-')k=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
s=(s<<3)+(s<<1)+(c^48);
c=getchar();
}
return s*k;
}
const int N=1e5+10;
ll T,n,m,p,a[N],b[N];
ll ksm(ll a,ll b){
ll t=1;
for(;b;b>>=1,a=a*a%p)
if(b&1) t=t*a;
return t;
}
ll init(ll n,ll p){
a[0]=1;
for(int i=1;i<=n;i++) a[i]=(a[i-1]*i)%p;
b[n]=ksm(a[n],p-2);
for(int i=n-1;i>=0;i--){
b[i]=b[i+1]*(i+1)%p;
}
}
ll C(ll n,ll m,ll p){
if(m>n) return 0;
return a[n]*b[m]%p*b[n-m]%p;
}
ll Lucas(ll n,ll m,ll p){
if(!m) return 1;
return (C(n%p,m%p,p)*Lucas(n/p,m/p,p))%p;
}
int main(){
T=read();
while(T--){
n=read();m=read();p=read();
init(p-1,p);
printf("%lld\n",Lucas(n+m,m,p)%p);
}
return 0;
}
这个东西的本质是:对
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!