枚举VIP的个数 x ,求出第一种人个数的范围 [L,R] 。
用类似求卡特兰数的方法可以得出答案为
#include
using namespace std;
#define N 100010
#define M 33
int i,j,k,n,m,p;
int a[M],c[N][M];
int fac[N],inv[N];
int l,r,L,R,len,Ans;
inline int Pow(int x,int y){
int Ans=1;
for(;y;y>>=1,x=1ll*x*x%p)if(y&1)Ans=1ll*Ans*x%p;
return Ans;
}
inline void Init(){
int t=p;
for(int i=2;i*i<=t;i++)
if(!(t%i)){
a[++m]=i;t/=i;
while(!(t%i))t/=i;
}
if(t>1)a[++m]=t;
int phi=p;
for(int i=1;i<=m;i++)phi=phi/a[i]*(a[i]-1);
fac[0]=inv[0]=1;
for(int i=1;iint x=i;
for(int j=1;j<=m;j++){
c[i][j]=c[i-1][j];
while(!(x%a[j]))x/=a[j],c[i][j]++;
}
fac[i]=1ll*fac[i-1]*x%p;
inv[i]=Pow(fac[i],phi-1);
}
}
inline int Calc(int x,int y){
if(x<y)return 0;
if(!y)return 1;
int Ans=1ll*fac[x]*inv[y]%p*inv[x-y]%p;
for(int i=1;i<=m;i++)Ans=1ll*Ans*Pow(a[i],c[x][i]-c[y][i]-c[x-y][i])%p;
return Ans;
}
int main(){
scanf("%d%d%d%d",&n,&p,&l,&r);
Init();
for(i=0;i<=n;i++)len=n-i,Ans=(Ans+1ll*(Calc(len,l+len+1>>1)-Calc(len,(min(r,len)+len>>1)+1))*Calc(n,i))%p;
if(Ans<0)Ans+=p;
cout<return 0;
}