题解大部分都是递归实现的,给出一种非递归的形式

话说上课老师讲的时候没给代码,然后自己些就写成了这样

对于质数\(p\)给出卢卡斯定理:

\[\tbinom{n}{m}=\tbinom{n \bmod p}{m \bmod p}\tbinom{\lfloor \frac{n}{p}\rfloor}{\lfloor \frac{m}{p} \rfloor}\pmod p
\]

其实它还有另一种形式,虽然本质上没啥区别:

\[\tbinom{n}{m}=\prod_{i=1}^k \tbinom{a_i}{b_i} \pmod p
\]

其中,\(a,b\)分别为\(n,m\)的\(p\)进制下的每一位,\(k\)是它们位数的较大值,当然如果有数不足\(k\)位,要补前导0


来证明一下

其实证明方法也是看了别人blog才知道的

设\(s=\lfloor \dfrac{n}{p}\rfloor,t=\lfloor \dfrac{m}{p}\rfloor\)

则有\(q,w\)使得\(n=sp+q,m=tp+w\)

再考虑一个二项式:

\[(1+x)^n=((1+x)^p)^s(1+x)^q
\]

 

先由费马小定理推个结论:

\[x^p\equiv x\pmod p \Rightarrow (x^p+1)\equiv (x+1)\pmod p
\]

\[(x+1)^p\equiv (x+1)\pmod p
\]

所以:

\[(x+1)^p\equiv (x^p+1)\pmod p
\]

 

把这个结论带进去:

\[(1+x)^n\equiv (1+x^p)^s(1+x)^q \pmod p
\]

再由二项式定理把右边展开

\[(1+x)^n\equiv \sum_{i=1}^s \tbinom{s}{i}x^{pi}\cdot \sum_{j=1}^q \tbinom{q}{j}x^j
\]

同样我们可以把左边展开:

\[(1+x)^n=\sum_{i=1}^{sp+q}\tbinom{sp+q}{i}x^i
\]

然后我们可以发现,左右两遍都有\(x^{tp+w}\)次项(当然,这是在\(m\leq n\)的情形下,如果\(m>n\)结果就是0,不用考虑了)

比较一下它们的系数

左边:\(\tbinom{sp+q}{tp+w}x^{tp+w}\)

右边:\(\tbinom{s}{t}x^{tp}\cdot \tbinom{q}{w}x^w\)

这边要说明一下,不会出现别的次数组合,比如\((t-1)p\)和\((w+p)\),因为\(w,q<p\)

所以:\(\tbinom{sp+q}{tp+w}\equiv \tbinom{s}{t}\tbinom{q}{w}\pmod p\)

即:

\[\tbinom{n}{m}\equiv\tbinom{n \bmod p}{m \bmod p}\tbinom{\lfloor \frac{n}{p}\rfloor}{\lfloor \frac{m}{p} \rfloor}\pmod p
\]

然后把\(\tbinom{\lfloor \frac{n}{p}\rfloor}{\lfloor \frac{m}{p} \rfloor}\)这一项不断展开,其实就变为了那种非递归形式


好了,我们终于得到了这个定理

那写代码就简单了,将\(n,m\)转化为\(p\)进制

预处理出阶乘数组,和阶乘的逆元数组

然后对于这\(p\)进制的每一位直接套组合数公式就行了

然而代码似乎没有递归的好写

另外一共5个点,我错了三遍下载了三个数据来调

那么说一下踩得坑,首先主函数for循环里的特判一定要有,避免出现数组下标变成负数,或者使用0的逆元的情况

还有多测时前导0的位置一定要清零

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<stack>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int n,m,p;
LL fac[200006],g[200006];
int a[100006],b[100006];
inline LL power(LL x,LL y){
reg LL ans=1;
while(y){
if(y&1) ans=(1ll*ans*x)%p;
y>>=1;x=(x*x*1ll)%p;
}
return ans;
}
std::stack<int>s;
inline void pre(){//预处理函数
a[0]=b[0]=0;
while(n){
s.push(n%p);n/=p;
}
while(!s.empty()) a[++a[0]]=s.top(),s.pop();
int tmp=0;
while(m){
tmp++;
s.push(m%p);m/=p;
}
while(b[0]+tmp<a[0]) b[++b[0]]=0;//前导零的位置一定要清零
while(!s.empty()) b[++b[0]]=s.top(),s.pop();
fac[0]=1;
for(reg int i=1;i<p;i++) fac[i]=(1ll*fac[i-1]*i)%p;
g[p-1]=power(fac[p-1],p-2);
for(reg int i=p-2;i;i--) g[i]=(1ll*g[i+1]*(i+1))%p;
}
int main(){int t=read();while(t--){
n=read();m=read();p=read();
n+=m;m=n-m;
// std::memset(a,0,sizeof a);std::memset(b,0,sizeof b);
pre();
// for(reg int i=1;i<=a[0];i++) std::printf("%d ",a[i]);EN;
// for(reg int i=1;i<=b[0];i++) std::printf("%d ",b[i]);EN;
// for(reg int i=0;i<p;i++) std::printf("%d ",fac[i]);EN;
// for(reg int i=0;i<p;i++) std::printf("%d ",g[i]);EN;
LL ans=1;
// std::printf("%d %d\n",a[0],b[0]);
for(reg int i=1;i<=a[0];i++){
if(!b[i]) continue;
if(a[i]<b[i]){ans=0;break;}
if(a[i]==b[i]) continue;
ans=(1ll*ans*fac[a[i]])%p;
ans=(1ll*ans*g[b[i]])%p;
ans=(1ll*ans*g[a[i]-b[i]])%p;
}
std::printf("%lld\n",ans);
}
return 0;
}

P3807【模板】卢卡斯定理的更多相关文章

  1. 【洛谷P3807】(模板)卢卡斯定理

    卢卡斯定理 把n写成p进制a[n]a[n-1][n-2]…a[0],把m写成p进制b[n]b[n-1][n-2]…b[0],则C(n,m)与C(a[n],b[n])*C(a[n-1],b[n-1])* ...

  2. 887. 求组合数 III(模板 卢卡斯定理)

    a,b都非常大,但是p较小 前边两种方法都会超时的  N^2 和NlongN  可以用卢卡斯定理  P*longN*longP     定义: 代码: import java.util.Scanner ...

  3. 洛谷.3807.[模板]卢卡斯定理(Lucas)

    题目链接 Lucas定理 日常水题...sublime和C++字体死活不同步怎么办... //想错int范围了...不要被longlong坑 //这个范围现算阶乘比预处理快得多 #include &l ...

  4. 【数论】卢卡斯定理模板 洛谷P3807

    [数论]卢卡斯定理模板 洛谷P3807 >>>>题目 [题目] https://www.luogu.org/problemnew/show/P3807 [输入格式] 第一行一个 ...

  5. P3807 【模板】卢卡斯定理

    P3807 [模板]卢卡斯定理 求 \(C_{m + n}^{m} \% p\) ( \(1\le n,m,p\le 10^5\) ) 错误日志: 数组开小(哇啊啊啊洼地hi阿偶我姑父阿贺佛奥UFO爱 ...

  6. 洛谷 P3807 【模板】卢卡斯定理

    P3807 [模板]卢卡斯定理 题目背景 这是一道模板题. 题目描述 给定n,m,p(1\le n,m,p\le 10^51≤n,m,p≤105) 求 C_{n+m}^{m}\ mod\ pCn+mm ...

  7. 洛谷——P3807 【模板】卢卡斯定理

    P3807 [模板]卢卡斯定理 洛谷智推模板题,qwq,还是太弱啦,组合数基础模板题还没做过... 给定n,m,p($1\le n,m,p\le 10^5$) 求 $C_{n+m}^{m}\ mod\ ...

  8. 【luogu P3807】【模板】卢卡斯定理/Lucas 定理(含 Lucas 定理证明)

    [模板]卢卡斯定理/Lucas 定理 题目链接:luogu P3807 题目大意 求 C(n,n+m)%p 的值. p 保证是质数. 思路 Lucas 定理内容 对于非负整数 \(n\),\(m\), ...

  9. 【刷题】洛谷 P3807 【模板】卢卡斯定理

    题目背景 这是一道模板题. 题目描述 给定\(n,m,p( 1\le n,m,p\le 10^5)\) 求 \(C_{n+m}^{m}\ mod\ p\) 保证 \(p\) 为prime \(C\) ...

随机推荐

  1. jsonpath 字典中取值

    jsonpath 第三方模块 def getsign(): url="http://api.nnzhp.cn/api/user/login" data = {"usern ...

  2. python3(三十) Enum

    """ """ __author__ = 'shaozhiqi' # 当我们需要定义常量时,一个办法是用大写变量通过整数来定义,例如月份: ...

  3. nginx内置高可用配置与第三方高可用模块nginx_ustream_check_mudule配置

    1. nginx 第三方高可用模块 IP 备注 10.0.0.63 proxy 10.0.0.64 web1 10.0.0.65 web2 这里会讲解一些nignx常用高可用方案,以及引入第三方高可用 ...

  4. 分享一本Java并发编程的免费好书

    最近当当的大促销又开始了,估计很多人脑子一热,又花钱囤了不少技术书吧. 在我看来大部分程序员买技术书的用途(以下排名按用途从大到小): 让领导.同事看见,你看我多爱学习: 给自己一个心理安慰,我还没废 ...

  5. tf.nn.sigmoid_cross_entropy_with_logits 分类

    tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None,,labels=None,logits=None,name=None) logits和la ...

  6. shell map数据结构的实现

    前言     Bash默认不支持二维数组,如果我们想实现map 数据结构,可以安装如下的方式来进行构造   预备知识     eval:  它是shell内建命令,用于字符串的解析.它会首先扫描命令行 ...

  7. [总结]RMQ问题&ST算法

    目录 一.ST算法 二.ST算法の具体实现 1. 初始化 2. 求出ST表 3. 询问 三.例题 例1:P3865 [模板]ST表 例2:P2880 [USACO07JAN]平衡的阵容Balanced ...

  8. 你自学半年也搞不懂的go底层,看这篇。这篇讲 go的数组、切片、Maps

    目录 数组 1.定义数组 2.使用数组 3.定义并赋值 4.数组的大小是类型的一部分 5.数组是值类型(当参数传递到函数中,修改不会改变原来的值) 6.数组长度 7.循环数组 8.多维数组 切片 1. ...

  9. shiro:入门程序(一)

    SpringMVC项目 1:pom引入相关依赖 <dependencies> <!--测试依赖--> <dependency> <groupId>jun ...

  10. Java 使用正则表达式和IO实现爬虫以及503解决

    我这边找了个小说网站: 基本套路: 第一步:获取小说每一章的url地址 第二步:获取章节url内容并使用正则表达式提取需要的内容 第三步:多线程封装,实现如下效果 最后测试. 代码: 内容获取封装: ...