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

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

对于质数\(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. Python进度条模块tqdm实现任务进度可视化

    一.前言 tqdm 是一个易用性强.扩展性高的 Python 进度条库,可以在 Python 长循环中添加一个进度提示信息,我们只需要封装任意的迭代器 tqdm(iterator) 即可. 二.安装 ...

  2. 搭建环境-Eclipse配置Tomcat创建Servlet总结

    Descripton:Web开发:Eclipse的下载与安装,Tomcat下载和结合Eclipse的使用,Eclipse使用Servlet[记录下总结下] 一.Eclipse的下载与安装 下载地址 注 ...

  3. Coin Change UVA

    Suppose there are 5 types of coins: 50-cent, 25-cent, 10-cent, 5-cent, and 1-cent. We want to makech ...

  4. Ubuntu搭建Redis 集群

    1.源码编译 查看需要下载版本:http://download.redis.io/releases/ 本人保存路径:/usr/local/soft/ wget http://download.redi ...

  5. [apue] getopt 可能重排参数

    看第21章时,介绍到了解析命令行的神器 getopt,了解了 linux 下处理通用命令行的方法. 命令行可分为参数与选项,其中不带 - 或 -- 前缀的为参数,对一个命令而言数量是固定的,多个参数之 ...

  6. 2007 NOIP T1奖学金

    奖学金(07NOIPT1): [题目描述] 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金.期末,每个学生都有3门课的成绩:语文.数学.英语.先按总分从高到低排序,如果 ...

  7. Java中的OOM问题

    OOM是什么 OOM全称"OutOfMemory",既内存溢出.我们知道,Java中的对象是在堆(heap)上创建的,当堆内存不足以为新创建的对象分配空间时,就会产生OutOfMe ...

  8. Java IO 流 -- 转换流: InputStreamReader OutputStreamWriter

    java 中 转换流是以字符流的形式操作字节流,需要注意一下两点: 1.操作内容必须是纯文本 2.指定字符集避免乱码 操作控制台输入输出: try (BufferedReader br = new B ...

  9. Caused by: java.io.IOException: Type mismath in vlaue from map: excepted org.apache.hadoop.io.InaWritable,received SC

    解决办法: 看map和reduce的输入是不是对应,看看map和reduce设置的参数和下面的是否一致

  10. thinkphp5.0.x

    payload5.0.24 http://-----/index.php?s=index/think\app/invokefunction&function=call_user_func_ar ...