bzoj 4767: 两双手 组合 容斥

时间:2022-11-26 01:06:40

题目链接

bzoj4767: 两双手

题解

不共线向量构成一组基底

对于每个点\((X,Y)\)构成的向量拆分

也就是对于方程组

$Ax * x + Bx * y = X \(
\)Ay * x + By * y = Y\(
\)x,y\(不能为负问题转化为NE lattice path
\)f(i)\(表示从0到i点不经过障碍的方案数
枚举第一个碰到的障碍点
\)f(i) = cnt(0,i) - \sum_j dp[j] cnt(j,i)$

\(cnt(x,y)\)为从点x到y的方案数

代码


#include<cstdio>
#include<algorithm>
#include<cstring>
#define gc getchar()
#define pc putchar
inline int read() {
int x = 0,f = 1;
char c = gc;
while(c < '0' || c > '9') {if(c == '-') f = -1 ; c = gc; }
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = gc;
return x * f;
}
void print(int x) {
if(x >= 10) print(x / 10);
pc(x % 10 + '0');
}
#define int long long
const int maxn = 507;
const int M = 500000;
const int mod = 1e9 + 7;
int Ex,Ey,n;
int Ax,Ay,Bx,By;
int f[maxn];
struct Node {
int x,y;
bool operator < (const Node a) const {
return x == a.x ? y < a.y : x < a.x;
}
} p[maxn];
int fac[M + 7],inv[M + 7];
inline int fstpow(int x,int k) {
int ret = 1;
for(;k;k >>= 1,x = 1ll * x * x % mod)
if(k & 1) ret = 1ll * ret * x % mod;
return ret;
}
inline void calc(int &x,int &y) {
int a1 = x * By - y * Bx,a2 = Ax * By - Ay * Bx;
int b1 = x * Ay - Ax * y,b2 = Bx * Ay - Ax * By;
if(!a2 || !b2) {x = y = -1;return; }
if((a1 % a2) || (b1 % b2)) {x = y = -1;return; }
x = a1 / a2,y = b1 / b2;
}
inline int C(int x,int y){
if(x < y) return 0;
return 1ll * fac[x] * inv[y] % mod * inv[x - y] % mod;
}
main() {
fac[0] = fac[1] = 1; for(int i = 1;i <= M;++ i) fac[i] = 1ll * fac[i - 1] * i % mod;
inv[0] = 1;
inv[M] = fstpow(fac[M],mod - 2); for(int i = M - 1;i >= 1;-- i) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod; Ex = read(),Ey = read(),n = read();
Ax = read(),Ay = read(),Bx = read(),By = read(); calc(Ex,Ey); for(int i = 1;i <= n;++ i) {
p[i].x = read(),p[i].y = read();
calc(p[i].x,p[i].y);
if(p[i].x < 0 || p[i].y < 0 || p[i].x > Ex || p[i].y > Ey) n --,i --;
}
p[0].x = p[0].y = 0;
p[++ n].x = Ex,p[n].y = Ey; std::sort(p + 1,p + n + 1); for(int i = 1;i <= n;++ i) {
f[i] = C(p[i].x + p[i].y,p[i].x);
if(f[i] == 0) continue;
for(int j = 1;j < i;++ j) {
f[i] -= (1ll * f[j] * C(p[i].x - p[j].x + p[i].y - p[j].y,p[i].x - p[j].x)) % mod;
f[i] %= mod;
f[i] += mod ;
f[i] %= mod;
}
}
print(f[n]);
return 0;
}