比较综合的一道题,需要用到中国剩余定理来进行取模.
Code:
#include <cstdio> #include <algorithm> #define N 1000006 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll F[N]; int array[10]={0,3,5,6793,10007}; struct Node { ll x,y; Node(ll x=0,ll y=0):x(x),y(y){} }arr[N]; bool cmp(Node a,Node b) { return a.x==b.x?a.y<b.y:a.x<b.x; } ll qpow(ll base,ll k,ll mod) { ll tmp=1; for(;k;k>>=1,base=base*base%mod) if(k&1) tmp=tmp*base%mod; return tmp; } struct Lucas { int mod; int fac[N]; int inv(int i) { return (int)qpow(i,mod-2,mod); } void init(int p) { mod=p,fac[0]=1; for(int i=1;i<=mod;++i) fac[i]=(ll)fac[i-1]*i%mod; } int C(int x,int y) { if(y>x) return 0; if(y==0) return 1; return (int)(1ll*fac[x]*inv(fac[y])%mod*inv(fac[x-y])%mod); } int solve(ll x,ll y) { if(y>x) return 0; if(y==0) return 1; return (int)(1ll*solve(x/mod,y/mod)*C(x%mod,y%mod)%mod); } }comb[8]; struct excrt { ll arr[N],brr[N]; ll exgcd(ll a,ll b,ll &x,ll &y) { if(!b) { x=1,y=0; return a; } ll gcd=exgcd(b,a%b,x,y),tmp=x; x=y,y=tmp-a/b*y; return gcd; } ll Excrt() { int i,j; ll ans=arr[1],M=brr[1]; for(i=2;i<=4;++i) { ll a=M,b=brr[i],c=arr[i]-ans,gcd,x,y; gcd=exgcd(a,b,x,y),b=abs(b/gcd); x=(x*(c/gcd)%b+b)%b; ans+=M*x; M*=brr[i]/__gcd(brr[i],M); ans=(ans%M+M)%M; } return ans; } }crt; ll C(ll a,ll b,int ty) { if(ty==0) return comb[0].solve(a,b); else { int i,j; for(i=1;i<=4;++i) { crt.arr[i]=comb[i].solve(a,b); crt.brr[i]=array[i]; } } return crt.Excrt(); } int main() { int i,j,k,flag; // setIO("input"); ll n,m,mod; scanf("%lld%lld%d%lld",&n,&m,&k,&mod),flag=(mod==1019663265); if(!flag) { comb[0].init(mod); } else { for(i=1;i<=4;++i) comb[i].init(array[i]); } for(i=1;i<=k;++i) scanf("%lld%lld",&arr[i].x,&arr[i].y); arr[++k].x=n,arr[k].y=m; sort(arr+1,arr+1+k,cmp); for(i=1;i<=k;++i) { F[i]=C(arr[i].x+arr[i].y,arr[i].y,flag); for(j=1;j<i;++j) { if(arr[j].y<=arr[i].y) F[i]=(F[i]-(F[j]*C(arr[i].x-arr[j].x+arr[i].y-arr[j].y,arr[i].y-arr[j].y,flag)%mod)+mod)%mod; } } printf("%lld\n",F[k]); return 0; }