#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. 报错initscripts conflicts with redhat-release-server-7.0-1.el7.x86_64

    报错 解决:删除冲突的rpm包即可 rpm -e redhat-release-server-7.0-1.el7.x86_64 --nodeps

  2. 使用C++日志库log4cplus

    用vs2015编译log4cplus,新建工程使用该库的时候出现连接错误,错误原因如下所述: 编译unicode版,可以正常使用了.

  3. Django项目:CRM(客户关系管理系统)--57--47PerfectCRM实现CRM客户报名流程02

    图片另存为  16*16  名字修改为      bpm_logo.jpg /*! *bootstrap.js * * Bootstrap v3.3.7 (http://getbootstrap.co ...

  4. IT外包概要

    IT外包 前两天和朋友聊起这个外包的问题,就顺便给他说了一下,自己也整理了一下,发出来,方便更多的人. 如果有说的不准确的地方欢迎大家补充分享. 大致分两种: 项目外包, 人力外包. 简而言之:项目外 ...

  5. SQL Server中存储过程与函数的区别

    本质上没区别.只是函数有如:只能返回一个变量的限制.而存储过程可以返回多个.而函数是可以嵌入在sql中使用的,可以在select中调用,而存储过程不行.执行的本质都一样. 函数限制比较多,比如不能用临 ...

  6. Python技巧—list与字符串互相转换

    Python技巧-list与字符串互相转换 在Python的编程中,经常会涉及到字符串与list之间的转换问题,下面就将两者之间的转换做一个梳理. 1.list转换成字符串 命令:list() 例子: ...

  7. 爱上一门语言不需要理由——我的js之路

    开始记录js学习:~~~~分享一下你的js学习途径吧 决定学习前端之后,开始接触JavaScript 1995年,网景公司的Brendan Eich用10天完成了JavaScript的设计,他被称为J ...

  8. python运~算~~符!!!!!!!!!!!

    目录: 算术运算, 用于加减乘除等数学运算 赋值运算,用于接收运算符或方法调用返回的结果 比较运算, 用于做大小或等值比较运算 逻辑运算,用于做 与.或.非运算 位运算, 用于二进制运算 每种运算中所 ...

  9. Linux Shell脚本经典案例

    开头加解释器:#!/bin/bash    语法缩进,使用四个空格:多加注释说明.    命名建议规则:变量名大写.局部变量小写,函数名小写,名字体现出实际作用.    默认变量是全局的,在函数中变量 ...

  10. Octave 软件的安装

    每次安装软件都感觉是一种心痛的历程.下载安装,然后就跳出一堆的错误,之后就各种百度求救,然后就搞了大半天,有时候还搞不定. 最后,搞定的时候发现,原来这么简单,结果时间就这样浪费了,所以还是把这个过程 ...