#include<bits/stdc++.h>
#define re register
#define int long long
using namespace std;
int T,n,m,mod,ans=;
inline int read(){
re int a=,b=;re char ch=getchar();
while(ch<''||ch>'')
b=(ch=='-')?-:,ch=getchar();
while(ch>=''&&ch<='')
a=(a<<)+(a<<)+(ch^),ch=getchar();
return a*b;
}
inline int qpow(re int a,re int b,re int p){
re int res=;a%=p;
for(;b;b>>=){
if(b&)res=res*a%p;
a=a*a%p;
}
return res%p;
}
inline int exgcd(re int a,re int b,re int &x,re int &y){
re int d=a;
if(!b){x=,y=;return a;}
d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
}
inline int inv(re int a,re int m){
re int x,y;
re int d=exgcd(a,m,x,y);
return d==?(m+x%m)%m:-;
}
inline int mul(re int n,re int pi,re int pk){
if(!n)return ;
re int ans=;
if(n/pk){
for(re int i=;i<=pk;i++)
if(i%pi) ans=ans*i%pk;
ans=qpow(ans,n/pk,pk);
}
for(re int i=;i<=n%pk;i++)
if(i%pi) ans=ans*i%pk;
return ans*mul(n/pi,pi,pk)%pk;
}
inline int C(re int n,re int m,re int p,re int pi,re int pk)
{
if(m>n)return ;
re int a=mul(n,pi,pk),b=mul(m,pi,pk),c=mul(n-m,pi,pk);
re int k=,ans;
for(re int i=n;i;i/=pi) k+=i/pi;
for(re int i=m;i;i/=pi) k-=i/pi;
for(re int i=n-m;i;i/=pi) k-=i/pi;
ans=a*inv(b,pk)%pk*inv(c,pk)%pk*qpow(pi,k,pk)%pk;
ans=ans*(p/pk)%p*inv(p/pk,pk)%p;
return ans;
}
inline int lucas(re int m,re int n,re int p){
re int x=p,ans=;
for(re int i=;i<=p;i++){
if(!(x%i)){
re int pk=;
while(!(x%i))pk*=i,x/=i;
ans=(ans+C(n,m,p,i,pk))%p;
}
}
return ans;
}
signed main(){
T=read(),mod=read();
n=read(),m=read();
if(mod==||T<n+m){puts("");return ;}
for(re int k=m;k<=(T+m-n)/;k++)
ans+=lucas(k,T,mod)%mod*lucas(k-m,T-k,mod)%mod*lucas((T+m+n-(k<<))/,T-(k<<)+m,mod)%mod;
printf("%lld\n",ans%mod);
return ;
}
 #include<bits/stdc++.h>
#define re register
#define ll long long
using namespace std;
ll T,n,m,mod,ans=;
inline ll read(){
re ll a=,b=;re char ch=getchar();
while(ch<''||ch>'')
b=(ch=='-')?-:,ch=getchar();
while(ch>=''&&ch<='')
a=(a<<)+(a<<)+(ch^),ch=getchar();
return a*b;
}
inline void exgcd(re ll &x,re ll &y,re ll a,re ll b)
{
if(!b){x=,y=;return;}
exgcd(x,y,b,a%b);
ll tmp=x;x=y;
y=tmp-a/b*y;
}
inline ll inv(re ll a,re ll p)
{
re ll x,y;
exgcd(x,y,a,p);
return x;
}
inline ll qpow(re ll a,re ll b,re ll p){
re ll res=;a%=p;
for(;b;b>>=){
if(b&)res=res*a%p;
a=a*a%p;
}
return res%p;
}
inline ll fac(re ll n,re ll p,re ll tp)
{
if(!n) return ;
re ll f=,res=;
for(re ll i=;i<tp;i++)
{
if(i%p) (f*=i)%=tp;
if(i==n%tp) res=f;
}
f=qpow(f,n/tp,tp);
return fac(n/p,p,tp)*f%tp*res%tp;
}
inline ll C(re ll m,re ll n,re ll p,re ll tp)
{
re ll ct=;
for(re ll i=m;i;i/=p) ct+=i/p;
for(re ll i=n;i;i/=p) ct-=i/p;
for(re ll i=m-n;i;i/=p) ct-=i/p;
return fac(m,p,tp)*inv(fac(n,p,tp),tp)%tp*inv(fac(m-n,p,tp),tp)%tp*qpow(p,ct,tp)%tp;
}
inline ll CRT(re ll m,re ll n,re ll p,re ll tp)
{
return C(m,n,p,tp)*(mod/tp)%mod*inv(mod/tp,tp)%mod;
}
inline ll lucas(re ll n,re ll m,re ll p)
{
ll ans=;
for(re ll i=;i*i<=p;i++)
{
if(p%i==)
{
re ll tp=;
while(p%i==) tp*=i,p/=i;
(ans+=CRT(m,n,i,tp))%=mod;
}
}
if(p!=) (ans+=CRT(m,n,p,p))%=mod;
return (ans%mod+mod)%mod;
}
signed main(){
T=read(),mod=read();
n=read(),m=read();
if(mod==||T<n+m){puts("");return ;}
for(re int k=m;k<=(T+m-n)/;k++)
ans+=lucas(k,T,mod)%mod*lucas(k-m,T-k,mod)%mod*lucas((T+m+n-(k<<))/,T-(k<<)+m,mod)%mod;
printf("%lld\n",ans%mod);
return ;
}

以下是ac代码

附上新的公式推导方式(经实测可AC)

设k为向上走的步数(纯的,不包括向下),那么向下走的步数为k-m

即C(T,k)×C(T-k,k-m);

由上式可推出 向右的与向左的步数之和为T-2*k+m,而向右的比向左的多n,利用和差公式,易得,向右的为(T-2*k+m+n)/2;

且k>=m,(T-2*k+m+n)/2>=n;可得,k->[m,(T+m-n)/2];

故整体公式为

  ∑(k->[m,(T+m-n)/2])(C(T,k)×C(T-k,k-m)×C(T-2*k+m,(T-2*k+m+n)/2));

 #include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define QAQ 100010
#define re register
#define int long long
#define ll long long
#define fup(i,a,b) for(re int i=a;i<=b;++i)
#define fdn(i,a,b) for(re int i=a;i>=b;--i)
int n,m,mod,t;
ll ans;
int fac[QAQ],inv[QAQ];
int tot,p[QAQ],w[QAQ];
inline int quick_fk_me(re int a,re int b,re int pk){
int ans=;
for(;b;b>>=){
if(b&)ans=1ll*ans*a%pk;
a=1ll*a*a%pk;
}
}
void exgcd(re ll a,re ll b,re ll &x,re ll &y){
if(b==){x=,y=;return;}
exgcd(b,a%b,x,y);
re int z=x;
x=y,y=z-a/b*y;
}
inline ll crt(){
re ll ans=,lcm=,x,y;
fup(i,,tot)lcm*=p[i];
fup(i,,tot){
re ll tmp=lcm/p[i];
exgcd(tmp,p[i],x,y);
x=(x%p[i]+p[i])%p[i];
ans=(ans+tmp*x*w[i])%lcm;
}
return (ans+lcm)%lcm;
}
inline void Get_fac_and_inv(re int top,re int pk){
fac[]=fac[]=inv[]=inv[]=;
fup(i,,top)fac[i]=1ll*fac[i-]*i%pk;
fup(i,,top)inv[i]=(pk-pk/i)*inv[pk%i]%pk;
fup(i,,top)inv[i]=1ll*inv[i-]*inv[i]%pk;
}
int CC(re int n,re int m,re int pk){
if(m>n)return ;
return fac[n]*inv[m]%pk*inv[n-m]%pk;
}
int lucas(re int n,re int m,re int pk){
if(!m)return ;
return CC(n%pk,m%pk,pk)*lucas(n/pk,m/pk,pk)%pk;
}
inline bool divide(int n){
re int top=sqrt(n);
fup(i,,top){
if(n%i)continue;
p[++tot]=i;
while(n%i==)n/=i;
}
if(n>)p[++tot]=n;
return tot==;
}
main(){
scanf("%lld%lld",&t,&mod);
scanf("%lld%lld",&n,&m);
if(n<)n=-n;
if(m<)m=-m;
re int st=m,ed=(t+m-n)>>;
if(divide(mod)){
Get_fac_and_inv(min(t,mod),mod);//什么纱吊错 妈耶 不求阶乘??!!
fup(k,st,ed)
ans=(ans+lucas(t,k,mod)*lucas(t-k,k-m,mod)%mod*lucas(t-*k+m,(t-*k+m-n)>>,mod)%mod)%mod;
printf("%lld\n",ans);
return ;
}
fup(i,,tot){
re int pk=p[i];
Get_fac_and_inv(min(t,pk),pk);
fup(k,st,ed)
w[i]=(w[i]+lucas(t,k,pk)*lucas(t-k,k-m,pk)%pk*lucas(t-*k+m,(t-*k+m-n)>>,pk)%pk)%pk;
}
printf("%lld\n",crt());
}
 #include<bits/stdc++.h>
#define re register
#define int long long
using namespace std;
int T,n,m,mod,ans=,tot=,fac[],pi,pk,p;
inline int read(){
re int a=,b=;re char ch=getchar();
while(ch<''||ch>'')
b=(ch=='-')?-:,ch=getchar();
while(ch>=''&&ch<='')
a=(a<<)+(a<<)+(ch^),ch=getchar();
return a*b;
}
inline int qpow(re int a,re int b){
re int res=;a%=pk;
for(;b;b>>=){
if(b&)res=res*a%pk;
a=a*a%pk;
}
return res%pk;
}
inline int getcnt(re int x){
return x?x/pi+getcnt(x/pi):;
}
inline int getsum(re int x){
return x?((x/pk?qpow(fac[pk],x/pk):)*fac[x%pk]%pk*getsum(x/pi)%pk):;
}
inline int C(re int x,re int y){
if(y>x)return ;
re int a0=getsum(x),b0=getcnt(x);
re int a1=getsum(y),b1=getcnt(y);
re int a2=getsum(x-y),b2=getcnt(x-y);
b0-=b1+b2;
if(b0>=tot)return ;//含质因子的个数
return a0*qpow(a1,p-)%pk*qpow(a2,p-)%pk*qpow(pi,b0)%pk;
}
inline int work(){
re int res=,a,b,c,d;
fac[]=;
for(re int i=;i<=pk&&i<=T;i++)
fac[i]=(i%pi)?fac[i-]*i%pk:fac[i-];//处理阶乘
a=,b=n,c=(T-n-m)>>,d=(T+m-n)>>;//各方向初值
while(c>=){
res=(res+C(T,a+b)*C(a+b,a)%pk*C(c+d,c)%pk)%pk;
++a,++b,--c,--d;
}//处理组合数,上下左右的道路可能性
return res;
}
signed main(){
T=read(),mod=read(),n=read(),m=read();
n=(n<)?-n:n;m=(m<)?-m:m;//处理负数
re int l=mod;
for(re int i=;l>;i++){
if(i*i>l)i=l;//分解质因数
if(l%i==){
pi=i,pk=,tot=;
while(l%pi==)
l/=pi,pk*=pi,++tot;
p=pk/pi*(pi-);
(ans+=work()%mod*(mod/pk)%mod*qpow(mod/pk,p-)%mod)%=mod;//CRT
}
}
printf("%lld\n",ans);
return ;
}

另有 学习笔记“组合数取模”推荐

组合数取模(lucas定理+CRT合并)(AC)的更多相关文章

  1. 组合数取模&&Lucas定理题集

    题集链接: https://cn.vjudge.net/contest/231988 解题之前请先了解组合数取模和Lucas定理 A : FZU-2020  输出组合数C(n, m) mod p (1 ...

  2. 组合数取模Lucas定理及快速幂取模

    组合数取模就是求的值,根据,和的取值范围不同,采取的方法也不一样. 下面,我们来看常见的两种取值情况(m.n在64位整数型范围内) (1)  , 此时较简单,在O(n2)可承受的情况下组合数的计算可以 ...

  3. hdu 3944 DP? 组合数取模(Lucas定理+预处理+帕斯卡公式优化)

    DP? Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0 ...

  4. [转]组合数取模 Lucas定理

    对于C(n, m) mod p.这里的n,m,p(p为素数)都很大的情况.就不能再用C(n, m) = C(n - 1,m) + C(n - 1, m - 1)的公式递推了. 这里用到Lusac定理 ...

  5. [hdu5226]组合数求和取模(Lucas定理)

    题意:给一个矩阵a,a[i][j] = C[i][j](i>=j) or 0(i < j),求(x1,y1),(x2,y2)这个子矩阵里面的所有数的和. 思路:首先问题可以转化为求(0,0 ...

  6. hdu 3037 费马小定理+逆元除法取模+Lucas定理

    组合数学推推推最后,推得要求C(n+m,m)%p 其中n,m小于10^9,p小于1^5 用Lucas定理求(Lucas定理求nm较大时的组合数) 因为p数据较小可以直接阶乘打表求逆元 求逆元时,由费马 ...

  7. BZOJ-1951 古代猪文 (组合数取模Lucas+中国剩余定理+拓展欧几里得+快速幂)

    数论神题了吧算是 1951: [Sdoi2010]古代猪文 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 1573 Solved: 650 [Submit ...

  8. BZOJ_2142_礼物_扩展lucas+组合数取模+CRT

    BZOJ_2142_礼物_扩展lucas+组合数取模 Description 一年一度的圣诞节快要来到了.每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物.不同的人物在小E 心目中的重要性不同 ...

  9. lucas定理解决大组合数取模

    LL MyPow(LL a, LL b) { LL ret = ; while (b) { ) ret = ret * a % MOD; a = a * a % MOD; b >>= ; ...

随机推荐

  1. vue-admin-template模板添加screenfull全屏插件

    先安装screenfull:npm install screenfull@4.2.0 --save    (注意版本号) 一.在\src\components目录下创建Screenfull文件夹,创建 ...

  2. 【心无旁骛】vue-ts-daily

    这是一个非常有意思的项目,我们先来看看效果 这个项目所用的技术也比较有意思,它的技术栈为vue2.5 + Typescript + vuex + vue-router 放下博主的项目地址吧,https ...

  3. IDEA取消形参名显示

    idea默认情况下如显示形参名,看起来有点不习惯 现在设置去掉 (1)点击工具栏上的快捷按钮(快捷键:alt + ctrl + s) 或者"File" -> "Se ...

  4. 移动端Web适配单位rem的坑,oppo r9手机出现错位bug

    我们做了一个抽奖的H5活动页面,被一个oppo R9手机客户反馈,抽奖的转盘错位了.刷新了好几次都不行.网上百度一搜真的有部分安卓手机有坑.赶紧修复bug.分享完整的rem.js代码出来.各位看官自己 ...

  5. Intelij Idea 2016破解

    在注册时选择License server,输入http://www.iteblog.com/idea/key.php,点击OK

  6. springcloud 与分布式系统(转载)

    原地址:http://blog.csdn.net/neosmith/article/details/51919038 本文不是讲解如何使用spring Cloud的教程,而是探讨Spring Clou ...

  7. spring MVC4 配置详解(个人记录)

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  8. meta标签中设置apple-itunes-app的意义

    告诉iphone的safari浏览器:这个网站对应的是哪个app <meta name="apple-itunes-app" content="app-id=589 ...

  9. HTML5中的数据集dataset和自定义属性data-*

    在html5中可为所有元素添加一种自定义的属性,这种属性的前缀以data-开头,比如:data-name,目的是为元素提供与页面渲染无关,但与dom元素强相关的属性.添加完自定义属性后我们可以通过元素 ...

  10. hihocoder 1142 三分·三分求极值(三分)

    题目1 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点 ...