# [容斥原理 DP] BZOJ 4767 两双手

Ans=Cmn+mfvpath(v,t)

fv$f_v$怎么求 从头开始DP就好了

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<set>
using namespace std;
typedef pair<int,int> abcd;
typedef long long ll;

const int P=1e9+7;
const int MAXN=1000005;

ll fac[MAXN],inv[MAXN];

inline void Pre(int n=500000){
fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%P;
inv[1]=1; for (int i=2;i<=n;i++) inv[i]=(ll)(P-P/i)*inv[P%i]%P;
inv[0]=1; for (int i=1;i<=n;i++) inv[i]=inv[i]*inv[i-1]%P;
}
inline ll C(int n,int m){
return fac[n]*inv[m]%P*inv[n-m]%P;
}

int ex,ey,ax,ay,bx,by;

inline bool calc(int x,int y,int &A,int &B){
int s=x*by-y*bx,t=ax*by-ay*bx;
if (s%t) return 0; else A=s/t;
s=x*ay-y*ax,t=bx*ay-by*ax;
if (s%t) return 0; else B=s/t;
return 1;
}
const int N=505;
#define X first
#define Y second
int n,m;
int tot; abcd pt[N];
int f[N];

inline ll path(int j,int i){
int dx=pt[i].X-pt[j].X;
int dy=pt[i].Y-pt[j].Y;
if (dx<0 || dy<0) return 0;
return C(dx+dy,dx);
}

int main(){
int A,B; int x,y; Pre();
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
if (!(calc(ex,ey,A,B) && A>=0 && B>=0))
return printf("0\n"),0;
else
n=A,m=B;
int tmp=tot; tot=0;
for (int i=1;i<=tmp;i++){
if (calc(x,y,A,B) && A>=0 && B>=0 && A<=n && B<=m)
pt[++tot]=abcd(A,B);
}
pt[++tot]=abcd(n,m);
sort(pt+1,pt+tot+1);
f[0]=1;
for (int i=1;i<=tot;i++){
f[i]=path(0,i);
for (int j=1;j<i;j++)
f[i]=(f[i]+P-(ll)f[j]*path(j,i)%P)%P;
}
printf("%d\n",f[tot]);
return 0;
}