• bzoj 4767: 两双手 组合 容斥


    题目链接

    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;  
    } 
    
  • 相关阅读:
    简单测试
    纸玫瑰
    Java 字符串编码 (保存成txt测试)
    创建 Filter
    jee中文名图片+tomcat ==> 中文乱码的另类处理(未成功)
    dom4j_01_02
    dom4j_01_01
    Java 字符串编码
    websocket

  • 原文地址:https://www.cnblogs.com/sssy/p/9762975.html
Copyright © 2020-2023  润新知