这题跟BZOJ3782 上学路径思路一样。
但是这道题的图不是网格图,这个时候就要重建一下图,首先我们发现,从起点走到一个点用的A走法和B走法的次数是固定的,假设A走法用了x次,B走法用了y次,那么可以列一个方程组:
{Ax∗x+Bx∗y=xiAy∗x+By∗y=yi
这样就可以求出从起点到 (xi,yi) 用了多少次A走法和B走法,那么把用A走法的次数想象成平面的x坐标,B走法的次数想象成y坐标,那么就可以建出一张网格图,就用BZOJ3782的做法就行了
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 1000010
#define p 1000000007
using namespace std;
typedef pair<int,int> pairs;
typedef long long ll;
int n,Ex,Ey,a1,a2,b1,b2,cnt;
ll f[N],fac[N],inv[N];
struct node{
int x,y;
friend bool operator <(node a,node b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
}w[N];
#define Nosol pairs(-1,-1)
inline pairs solve_eq(int A,int B){
if((B*b1-A*b2)%(a2*b1-a1*b2)) return Nosol;
int x=(B*b1-A*b2)/(a2*b1-a1*b2);
if((B*a1-A*a2)%(a1*b2-a2*b1)) return Nosol;
int y=(B*a1-A*a2)/(a1*b2-a2*b1);
if(x<0||y<0) return Nosol;
return pairs(x,y);
}
inline ll C(int x,int y){
return fac[x]*inv[y]%p*inv[x-y]%p;
}
inline ll Get(int a,int b){
int A=w[b].x-w[a].x,B=w[b].y-w[a].y;
if(A<0||B<0) return 0;
return C(A+B,A);
}
int main(){
scanf("%d%d%d",&Ex,&Ey,&n);
scanf("%d%d%d%d",&a1,&a2,&b1,&b2);
pairs A=solve_eq(Ex,Ey);
if(A==Nosol) return puts("0"),0;
w[++cnt].x=A.first; w[cnt].y=A.second;
for(int i=1,x,y;i<=n;i++){
scanf("%d %d",&x,&y);
pairs A=solve_eq(x,y);
if(A!=Nosol&&A.first<=w[1].x&&A.second<=w[1].y) w[++cnt].x=A.first,w[cnt].y=A.second;
}
fac[0]=fac[1]=inv[0]=inv[1]=1;
for(ll i=2;i<=600000;i++) fac[i]=fac[i-1]*i%p;
for(ll i=2;i<=600000;i++) inv[i]=1ll*(p-p/i)*inv[p%i]%p;
for(int i=2;i<=600000;i++) inv[i]=inv[i]*inv[i-1]%p;
sort(w+1,w+1+cnt);
for(int i=1;i<=cnt;i++){
f[i]=C(w[i].x+w[i].y,w[i].x);
for(int j=1;j<i;j++)
f[i]=((f[i]-f[j]*Get(j,i))%p+p)%p;
}
printf("%lld\n",f[cnt]);
return 0;
}