Lucas定理

先上结论:

当p为素数:

\(\binom{ N }{M} \equiv \binom{ N/p }{M/p}*\binom{ N mod p }{M mod p} (mod p)\)

证明:令 \(s=\lfloor \frac{n}{p} \rfloor\),\(q=n\bmod p\),\(t=\lfloor \frac{m}{p} \rfloor\),\(r=m \bmod p\)。

需证明 \(\binom{sp+q}{tp+r}\equiv \binom{s}{t}\binom{q}{r} \pmod p\)。\((1+x)^n\equiv (1+x)^{sp+q}\equiv((1+x)^p)^s(1+x)^q\)。

因为 \((1+x)^p=\sum\limits_{i=0}^p \binom{p}{i} x^i\),

所以 \((1+x)^p\equiv(1+x^p)\)。

那么就有 \((1+x)^n\equiv(1+x^p)^s(1+x)^q\equiv\sum\limits_{i=0}^{s} \binom{s}{i} x^{pi}\cdot\sum\limits_{j=0}^q \binom{q}{i}x^i\)。

考虑 \(\binom{n}{m}\) 也就是 \(\binom{sp+q}{tp+r}\)

实际上是在多项式 \((1+x)^n\) 中 \(x^{tp+r}\) 项的系数,

由前面的同余式得到这个系数同时也是 \(\binom{s}{t}\binom{q}{r}\) 也就是 \(i\) 取 \(t\) \(j\) 取 \(r\) 的情况,

所以 \(\binom{n}{m}\equiv \binom{\lfloor \frac{n}{p} \rfloor}{\lfloor \frac{m}{p} \rfloor} \binom{n\bmod p}{m\bmod p} \pmod {p}\) 得证。

以上出自 ZCDHJ 的友情提供

也就是说我们对于 \(\binom{ N }{M} mod p\) 可以化为 \(\binom{ N/p }{M/p}*\binom{ N mod p }{M mod p} (mod p)\)

而 \(\binom{ N/p }{M/p}\) 显然可以继续递归调用下去

代码(可过luogu 模板):

#include<bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define ll long long
#define int ll
#define get getchar()
in int read()
{
int t=0; char ch=get;
while(ch<'0' || ch>'9') ch=get;
while(ch<='9' && ch>='0') t=t*10+ch-'0',ch=get;
return t;
}
const int _=1e6+5;
int n,m,p;
ll fac[_];
in ll fastpow(int a,int b) //快速幂
{
ll res=1;
while(b)
{
if(b&1)
res=(res*a)%p;
a=a*a%p,b>>=1;
}
return res;
}
in ll C(int a,int b) //组合数
{
if (a < b) return 0;
return fac[a]*fastpow(fac[b],p-2)%p*fastpow(fac[a-b],p-2)%p;
}
in ll lucas(int a,int b)//卢卡斯
{
if(!b) return 1;
return C(a%p,b%p)*lucas(a/p,b/p)%p; //显然C(a%p,b%p)不可能再用卢卡斯化简.所以直接暴力求
}//所以Lucas 通常只用于模数较小时
signed main()
{
int T=read();
while(T--)
{
n=read(),m=read(),p=read();
n+=m;
fac[0]=1;
for(re int i=1;i<=p;i++)
fac[i]=(fac[i-1]*i)%p;
cout<<lucas(n,m)<<endl;
}
return 0;
}

例题解析([SHOI2015]超能粒子炮·改)

传送门

题意简化

求 \(\sum\limits_{i=0}^{k} \binom{n}{i}\) mod p

p为2333

Solution

(以下用 % 表示mod,除法视作向下取整)

不妨设 \(F(n,k)=\sum\limits_{i=0}^{k} \binom{n}{i} mod p\)

根据Lucas 可推出

\(F(n,k)=\sum\limits_{i=0}^{k} \binom{n/p}{i/p} * \binom{n%p}{i%p}mod p\) (因为式子最后都要mod p,所以以下就省略了)

因为除法是向下取整的

考虑数论分块 (就是在1~n 枚举时若其中含除法,可以把每n/const 分为一块,每一块中的取值时一样的)

则有 \(F(n,k)=\sum\limits_{i=0}^{k/p} \binom{n/p}{i} * \sum\limits_{j=0}^{min(p-1,k-p*i)} \binom{n%p}{j}\)

再观察一下 min(p-1,k-pi) ,

可以发现只有 k-p
i==k%p 时才会小于 p-1,

而此时 i=k/p

所以我们又可以把式子再次拆开:

$ F(n,k)= \sum\limits_{i=0}^{k/p} \binom{n/p}{i} $ \(*\) $ \sum\limits_{j=0}^{p-1} \binom{n%p}{j}$ \(+\) $ \binom{n/p}{i/p} $ \(*\) $ \sum\limits_{j=0}^{k mod p} $ \(*\) $\binom{n%p}{j} $

$ \sum\limits_{i=0}^{k/p} \binom{n/p}{i} $ 是 F(n/p.k/p-1),

$ \sum\limits_{j=0}^{p-1} \binom{n%p}{j} $与 $ \sum\limits_{j=0}^{k mod p} $ \(*\) $\binom{n%p}{j} $ 则可以通过暴力预处理出

(因为模数较小)

然后 我们熟悉的 $ \binom{n/p}{i/p} $ 直接用卢卡斯就好了

代码

#include<bits/stdc++.h>
using namespace std;
#define re register
#define int long long
#define in inline
#define get getchar()
in int read()
{
int t=0; char ch=get;
while(ch<'0' || ch>'9') ch=get;
while(ch<='9' && ch>='0')t=t*10+ch-'0', ch=get;
return t;
}
const int mod=2333;
const int _=3005;
int C[_][_],sum[_][_];
in int lucas(int n,int m)
{
if(!m||n==m) return 1;
if(n<m) return 0;
return lucas(n/mod,m/mod)*C[n%mod][m%mod]%mod;
}
in int work(int n,int k)
{
if(k<0)
return 0;
if(!n||!k)
return 1;
if(n<=mod&&k<=mod) return sum[n][k];
return (work(n/mod,k/mod-1)*sum[n%mod][mod-1]%mod+lucas(n/mod,k/mod)*sum[n%mod][k%mod]%mod)%mod;
}
signed main()
{
int T=read();
sum[0][0]=C[0][0]=1;
for(re int i=1;i<=mod+3;i++)
sum[i][0]=C[i][0]=C[i][i]=1;
for(re int i=1;i<=mod+3;i++)
for(re int j=1;j<i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; //预处理组合数(杨辉三角)
for(re int i=0;i<=mod+3;i++)
for(re int j=1;j<=mod+3;j++)
sum[i][j]=(C[i][j]+sum[i][j-1])%mod; //预处理杨辉三角同一行的前缀和
while(T--)
{
int n=read(),k=read();
cout<<work(n,k)<<endl;
}
return 0;
}

Lucas(卢卡斯)定理模板&&例题解析([SHOI2015]超能粒子炮·改)的更多相关文章

  1. Bzoj 4591: [Shoi2015]超能粒子炮·改 数论,Lucas定理,排列组合

    4591: [Shoi2015]超能粒子炮·改 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 178  Solved: 70[Submit][Stat ...

  2. bzoj 4591: [Shoi2015]超能粒子炮·改 [lucas定理]

    4591: [Shoi2015]超能粒子炮·改 题意:多组询问,求 \[ S(n, k) = \sum_{i=0}^n \binom{n}{i} \mod 2333,\ k \le n \le 10^ ...

  3. 【BZOJ4591】[SHOI2015]超能粒子炮·改 (卢卡斯定理)

    [BZOJ4591][SHOI2015]超能粒子炮·改 (卢卡斯定理) 题面 BZOJ 洛谷 题解 感天动地!终于不是拓展卢卡斯了!我看到了一个模数,它是质数!!! 看着这个东西就感觉可以递归处理. ...

  4. BZOJ_4591_[Shoi2015]超能粒子炮·改_Lucas定理

    BZOJ_4591_[Shoi2015]超能粒子炮·改_Lucas定理 Description 曾经发明了脑洞治疗仪&超能粒子炮的发明家SHTSC又公开了他的新发明:超能粒子炮·改--一种可以 ...

  5. bzoj4591 / P4345 [SHOI2015]超能粒子炮·改

    P4345 [SHOI2015]超能粒子炮·改 题意:求$\sum_{i=1}^{k}C(n,i)\%(P=2333)$ 肯定要先拆开,不然怎么做呢(大雾) 把$C(n,i)$用$lucas$分解一下 ...

  6. 洛谷 P4345 [SHOI2015]超能粒子炮·改 解题报告

    P4345 [SHOI2015]超能粒子炮·改 题意 求\(\sum_{i=0}^k\binom{n}{i}\),\(T\)组数据 范围 \(T\le 10^5,n,j\le 10^{18}\) 设\ ...

  7. 【bzoj4591】[Shoi2015]超能粒子炮·改 Lucas定理

    题目描述 曾经发明了脑洞治疗仪&超能粒子炮的发明家SHTSC又公开了他的新发明:超能粒子炮·改--一种可以发射威力更加强大的粒子流的神秘装置.超能粒子炮·改相比超能粒子炮,在威力上有了本质的提 ...

  8. [bzoj4591][Shoi2015][超能粒子炮·改] (lucas定理+组合计数)

    Description 曾经发明了脑洞治疗仪&超能粒子炮的发明家SHTSC又公开了他的新发明:超能粒子炮·改--一种可以发射威力更加 强大的粒子流的神秘装置.超能粒子炮·改相比超能粒子炮,在威 ...

  9. P4345 [SHOI2015]超能粒子炮·改 Lucas

    \(\color{#0066ff}{ 题目描述 }\) 曾经发明了脑洞治疗仪与超能粒子炮的发明家 SHTSC 又公开了他的新发明:超能粒子炮・改--一种可以发射威力更加强大的粒子流的神秘装置. 超能粒 ...

随机推荐

  1. nginx+tomcat集群方法

    下载地址:wget http://nginx.org/download/nginx-1.16.1.tar.gz 解压:tar -zxvf 预编译 nginx+tomcat集群方法: 进入nginx配置 ...

  2. Python-临时文件文件模块-tempfile

    案例: 某项目中,从传感器中获得采集数据,每收集到1G的数据后做是数据分析,最终只保留数据分析的结果,收集到的数据放在内存中,将会消耗大量内存,我们希望把这些数据放到一个临时的文件中 临时文件不能命名 ...

  3. SPI应用 用SPI总线读取气压传感器SCP1000的数据

    Using SPI to read a Barometric Pressure Sensor This example shows how to use the SPI (Serial Periphe ...

  4. 1.入门篇十分钟了解Spring Cloud

    文章目录 Spring Cloud入门系列汇总 为什么需要学习Spring Cloud 什么是Spring Cloud 设计目标与优缺点 设计目标 优缺点 Spring Cloud发展前景 整体架构 ...

  5. 零基础小白Python入门必看:面向对象之典型魔术方法

  6. rm -rf /*真的能删掉所有文件吗?

    大佬们对于小白问的问题经常直接就是一个rm -rf /*丢过去(逃,被丢了很多次,所以印象深刻),但玩了这么久的梗,当我真正想删库的时候,这条命令却然并卵(滑稽,删库跑路都跑不成). 查看了下文件属性 ...

  7. idea报“Cannot resolve symbol XXX”错误

    解决方案

  8. 2016-12-04---tiny412平台下的iconv库的移植问题

    一.解决问题    在arm开发板上使用framebuff,在汉字显示时,因为只有gb2312的16*16的汉字字库,而ubuntu16.04默认    的编码方式时utf-8,因此需要进行转码(ut ...

  9. k8s集群添加新得node节点

    服务端操作: 方法一: 获取master的join token kubeadm token create --print-join-command 重新加入节点 kubeadm join 192.16 ...

  10. Python爬虫框架--Scrapy安装以及简单实用

    scrapy框架 框架 ​ -具有很多功能且具有很强通用性的一个项目模板 环境安装: Linux: ​        pip3 install scrapy ​ ​ ​  Windows: ​     ...