#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. Django logging 的配置方法

    做开发离不开日志,以下是我在工作中写Django项目常用的logging配置. BASE_LOG_DIR = os.path.join(BASE_DIR, "log") LOGGI ...

  2. python学习笔记3.3_json解析

    一.json文件读取 源文件:exampl.json 二.json在线解析 常用网站:https://www.json.cn/  三.数据导出为json格式文件

  3. 基于neighborhood models(item-based) 的个性化推荐系统

    文章主要介绍的是koren 08年发的论文[1],  2.2neighborhood models部分内容(其余部分会陆续补充上来). koren论文中用到netflix 数据集, 过于大, 在普通的 ...

  4. MFC编译Freetype2.3.7

    从http://www.freetype.org下载源代码. FreeType2库源码包中包含多种环境与编译器下的make文件,其中还包含vc的项目文件. 我用的是VC,所以首先找到VC环境的项目文件 ...

  5. 解决使用mybatis模糊查询为空的问题

    解决方法: 在数据库配置的url后添加?useUnicode=true&characterEncoding=utf-8 参考: https://blog.csdn.net/IT_private ...

  6. C语言内存布局简记待补充

    C语言存储类型总结内存操作函数总结 用于自己学习和记录 1. void *memset(void *s, int c, size_t n); #include <string.h> 功能: ...

  7. 洛谷 P2886 [USACO07NOV]牛继电器Cow Relays

    题面 解题思路 ## floyd+矩阵快速幂,跟GhostCai爷打赌用不用离散化,最后完败..GhostCai真是tql ! 有个巧妙的方法就是将节点重新编号,因为与节点无关. 代码 #includ ...

  8. React 组件&Props

    组件&Props 组件&Props 组件可以将UI切分成一些独立的.可复用的部件,这样你就只需要专注于构建每一个单独的组件. 组件从概念上看就像是函数,它可以接受任意的输入值(称之为& ...

  9. php四种文件加载语句

    https://mp.weixin.qq.com/s/Wsn4grDRxVIgMfu__E_oWQ 1.include 2.require 3.include_once 4.require_once ...

  10. cgroups实验

    # yum install -y libcgroup libcgroup-tools创建控制组cgcreate -g cpu:/testcgcreate -g cpu:/test2 禁用quotacg ...