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. Centos-强制将内存中数据写入磁盘-sync

    sync 强制将内存中数据写入磁盘,以免数据丢失.在linux系统中,修改过的操作并不会立即写入磁盘,而是先写到内存中,通过buffer队列当达到指定时间或者指定大小再一次性写入磁盘,提高IO效率,正 ...

  2. 第一次面试linux后台岗位

    今天给大家分享前段时间面试linux后台的面试题目,我从里面挑了几道大家比较陌生的题目,而且要那种手写代码的题目,这方面肯定很多人在实际面试时最怕的题目! 1.请说出如何用tcp服务实现文件的断点续传 ...

  3. C++vector and opencv Mat

    转载:https://blog.csdn.net/u012507022/article/details/50979011?utm_source=blogxgwz5 最近在写Opencv程序,用到离散小 ...

  4. C#实现——十大排序算法之选择排序

    选择排序法 1.工作原理(算法思路) 给定一个待排序数组,找到数组中最小的那个元素 如果最小元素不是待排序数组的第一个元素,则将其和第一个元素互换 在剩下的元素中,重复1.2过程,直到排序完成. 2. ...

  5. 使用Appium进行iOS的真机自动化测试

    windows不支持appium连接ios,只适用于mac 使用Appium进行iOS的真机自动化测试 安装类库 Homebrew 如果没有安装过Homebrew,先安装[ homebrew ] np ...

  6. Nginx作为反向代理时传递客户端IP的设置方法

    因为nginx的优越性,现在越来越多的用户在生产环境中使用nginx作为前端,不管nginx在前端是做负载均衡还是只做简单的反向代理,都需要把日志转发到后端real server,以方便我们检查程序的 ...

  7. laravel 500错误的一种可能

    报这个错误,我一度认为,再加上,百度,大家都说是配置有问题,经过我不断地问我学长,结果就是一个小错误,简直太丢人了. 居然是少了一个括号的问题,自闭了

  8. Python+Appium自动化测试(7)-截图方法

    一,selenium模块的两种截图方法 get_screenshot_as_file(filename) 参数filename为截图文件保存的绝对路径,如: driver.get_screenshot ...

  9. Vim最强调试插件:vimspector

    最近看到了韦大在知乎的回答后,想去试用一下vimspector,却发现vimspector诞生两年了却没有介绍它的中文资料.我查阅官方文档遇到不少困难,在这里记录折腾出来的结果,与大家分享. vims ...

  10. 如何把C++的源代码改写成C代码?而C改C++只需一步!

    ★ 如何把C++的源代码改写成C代码? C++解释器比C语言解释器占用的存储空间要大,想要在某些特定场合兼容C++代码,同时为了节省有限的存储空间,降低成本,也为了提高效率,将用C++语言写的源程序用 ...