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

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

对于质数\(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. 31.1 Exception 的method :getMessage()、 printStackTrace()

    package day31_exception; import java.lang.Exception; /* * Throwable的常用方法: String getMessage() :原因 St ...

  2. STC15F2K60S2串口通信的应用。

    前言:由于不可抗拒因素,初始的STC12C5A60S2芯片由于无法进行烧录(...因为没带有锁紧座的开发板),暂且使用STC15F2K60S2芯片.. 一 串行通信概述: 串口通信有SPI IIC U ...

  3. 子域名爆破工具:OneForALL

    0x00 简介 OneForAll是一款功能强大的子域收集工具 0x01 下载地址 码云: https://gitee.com/shmilylty/OneForAll.git Github: http ...

  4. 【小学数学】算术口诀 独立音频MP3

    算术口诀 独立音频MP3 原文载于本人个人网站:http://www.unlimitedbladeworks.cc/writing_202004_01_sskj 特点 加法口诀 乘法口诀 独立音频 m ...

  5. threejs 鼠标移动控制模型旋转

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  6. day5 作业

    tips:作业 作业: 0.分别画出下面两个列表在内存中是如何存放的 l1=[11,22,[333,444]] l2=[11,22,[33,{'name':'egon','age':18}]] ''' ...

  7. C. 无穷的小数

    单点时限: 1.0 sec 内存限制: 512 MB 在十进制下,我们能够很轻易地判断一个小数的位数是有穷的或无穷的,但是把这个小数用二进制表示出的情况下其有穷性和无穷性就会发生改变,比如 十进制下的 ...

  8. 玩转控件:Fucking ERP之流程图

    前言 首先,跟守护在作者公众号和私信作者催更的朋友们道个歉.疫情的原因,公司从年初到现在一直处于996+的高压模式,导致公众号更新频率较低.而且作者每更新一篇原创公众号,既要对自己沉淀知识负责,也要对 ...

  9. idea中哪些好用到飞起的插件,偷懒神器

    idea中开发人员的偷懒神器-插件  本期推荐一些开发人员常用的一些idea插件.偷懒神器在此,不再秃头! 1. idea安装插件的方法.  file->setting->plugins ...

  10. srt字幕翻译

    需要把字幕名改成i.txt 有有道和谷歌 代码: #Author:Chenglong Qian #Copyright :Chenglong Qian import json import reques ...