不考虑障碍
从(0,0)走到(n,m)的方案数为C(n,n+m)
先把障碍按照横坐标第一关键字,纵坐标第二关键字排序
f[i]表示不经过前i-1个障碍经过第i个障碍的方案数
f[i]=C(a[i].x,a[i].x+a[j].x)-∑f[j]*C(a[i].x-a[j].x,a[i].x-a[j].x+a[i].x-a[j].y) (a[j].x<=a[i].x,a[j].y<=a[i].y)
从(0,0)走到(n,m)的方案数为C(n,n+m)
先把障碍按照横坐标第一关键字,纵坐标第二关键字排序
f[i]表示不经过前i-1个障碍经过第i个障碍的方案数
f[i]=C(a[i].x,a[i].x+a[j].x)-∑f[j]*C(a[i].x-a[j].x,a[i].x-a[j].x+a[i].x-a[j].y) (a[j].x<=a[i].x,a[j].y<=a[i].y)
把(N,M)当成障碍加进去,最后输出f[T+1]就可以了
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
struct yts
{
long long x,y;
}a[1010];
long long n,m,P;
long long p[10];
long long fac[5][1000010],inv[5][1000010];
long long f[1010];
long long g[10],sum[10],Inv[10];
int num;
bool w=0;
bool cmp(yts x,yts y)
{
return x.x<y.x || (x.x==y.x && x.y<y.y);
}
long long power(long long x,long long y,long long p)
{
long long ans=1;
while (y)
{
if (y&1) ans=ans*x%p;
x=x*x%p;
y>>=1;
}
return ans;
}
long long c(long long x,long long y,int i)
{
if (x<p[i] && y<p[i]) return (fac[i][y]*inv[i][x]%p[i])*inv[i][y-x]%p[i];
else return c(x%p[i],y%p[i],i)*c(x/p[i],y/p[i],i)%p[i];
}
long long C(long long x,long long y)
{
if (!w) return c(x,y,0);
else
{
for (int i=1;i<=4;i++) g[i]=c(x,y,i);
long long ans=0;
for (int i=1;i<=4;i++) ans=(ans+(g[i]*sum[i]%P)*Inv[i]%P)%P;
return ans;
}
}
int main()
{
scanf("%lld%lld%d%lld",&n,&m,&num,&P);
for (int i=1;i<=num;i++) scanf("%lld%lld",&a[i].x,&a[i].y);
a[++num].x=n;a[num].y=m;
sort(a+1,a+num+1,cmp);
if (P!=1000003) p[1]=3,p[2]=5,p[3]=6793,p[4]=10007,w=1; else p[0]=1000003;
if (w)
{
for (int j=1;j<=4;j++)
{
fac[j][0]=1;sum[j]=P/p[j];Inv[j]=power(sum[j],p[j]-2,p[j]);
for (int i=1;i<p[j];i++) fac[j][i]=(long long)fac[j][i-1]*i%p[j];
inv[j][p[j]-1]=power(fac[j][p[j]-1],p[j]-2,p[j]);
for (int i=p[j]-2;i>=0;i--) inv[j][i]=(long long)inv[j][i+1]*(i+1)%p[j];
}
}
else
{
fac[0][0]=1;
for (int i=1;i<P;i++) fac[0][i]=(long long)fac[0][i-1]*i%P;
inv[0][P-1]=power(fac[0][P-1],P-2,P);
for (int i=P-2;i>=0;i--) inv[0][i]=(long long)inv[0][i+1]*(i+1)%P;
}
for (int i=1;i<=num;i++)
{
f[i]=C(a[i].x,a[i].x+a[i].y);
for (int j=1;j<i;j++)
if (a[j].x<=a[i].x && a[j].y<=a[i].y) f[i]=(f[i]-f[j]*C(a[i].x-a[j].x,a[i].x-a[j].x+a[i].y-a[j].y)%P+P)%P;
}
printf("%lld\n",f[num]);
return 0;
}