4767: 两双手

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 1057  Solved: 318
[Submit][Status][Discuss]

Description

老W是个棋艺高超的棋手,他最喜欢的棋子是马,更具体地,他更加喜欢马所行走的方式。老W下棋时觉得无聊,便
决定加强马所行走的方式,更具体地,他有两双手,其中一双手能让马从(u,v)移动到(u+Ax,v+Ay)而另一双手能让
马从(u,v)移动到(u+Bx,v+By)。小W看见老W的下棋方式,觉得非常有趣,他开始思考一个问题:假设棋盘是个无限
大的二维平面,一开始马在原点(0,0)上,若用老W的两种方式进行移动,他有多少种不同的移动方法到达点(Ex,Ey
)呢?两种移动方法不同当且仅当移动步数不同或某一步所到达的点不同。老W听了这个问题,觉得还不够有趣,他
在平面上又设立了n个禁止点,表示马不能走到这些点上,现在他们想知道,这种情况下马有多少种不同的移动方
法呢?答案数可能很大,你只要告诉他们答案模(10^9+7)的值就行。
 

Input

第一行三个整数Ex,Ey,n分别表示马的目标点坐标与禁止点数目。
第二行四个整数Ax,Ay,Bx,By分别表示两种单步移动的方法,保证Ax*By-Ay*Bx≠0
接下来n行每行两个整数Sxi,Syi,表示一个禁止点。
|Ax|,|Ay|,|Bx|,|By| <= 500, 0 <= n,Ex,Ey <= 500
 

Output

仅一行一个整数,表示所求的答案。
 

Sample Input

4 4 1
0 1 1 0
2 3

Sample Output

40

Solution

看起来很像一般的网格图求路径数,在没有障碍物的情况下,处理出到达终点分别用两种步数走的步数(解方程唯一固定,再用组合数学,方案数就等于$C(x+y,x)$,$x$和$y$分别是两种步数的次数。

可是这道题有障碍格。

所以在上述基础上进行容斥DP即可。将能走到的所有障碍点的$x$和$y$(从原点出发)预处理出来,(将终点的$x$、$y$值也放入结构体)排序后,后面的DP值要容斥减去前面能到达它的方案数。最后答案就是$dp[n]$。(因为一开始保证了结构体里所有障碍点都比目标点要小)

【注意】预处理阶乘的逆元线性从后往前线性求得,不然会TLE!

Code

#include<bits/stdc++.h>
#define mod 1000000007
#define LL long long
using namespace std; int Ax, Ay, Bx, By, n, Ex, Ey; struct Node {
int x, y;
} QAQ[];
bool cmp(Node a, Node b) { if(a.x == b.x) return a.y < b.y; return a.x < b.x; } LL mpow(LL a, LL b) {
LL ans = ;
for(; b; b >>= , a = a * a % mod)
if(b & ) ans = ans * a % mod;
return ans;
} void cal(int &x, int &y) {////解方程计算两种步数
LL a1, a2, b1, b2;
b1 = y * Ax - x * Ay, b2 = Ax * By - Ay * Bx;
a1 = x * By - y * Bx, a2 = Ax * By - Ay * Bx;
if(a2 == || b2 == ) { x = -, y = -; return ; }
if((a1 / a2) * a2 != a1 || (b1 / b2) * b2 != b1) { x = -, y = -; return ; }
x = a1 / a2, y = b1 / b2;
} LL fac[], inv[];
LL C(LL a, LL b) {
if(a < b) return ;
return fac[a] * inv[a-b] % mod * inv[b] % mod;
} void init() {
fac[] = ;
for(int i = ; i <= ; i ++)
fac[i] = fac[i-] * i % mod;
inv[] = ; inv[] = mpow(fac[], mod - );
for(int i = ; i >= ; i --)
inv[i] = inv[i + ] * (i + ) % mod;////线性求阶乘逆元
} LL f[];
int main() {
scanf("%d%d%d", &Ex, &Ey, &n);
scanf("%d%d%d%d", &Ax, &Ay, &Bx, &By);
cal(Ex, Ey);
for(int i = ; i <= n; i ++) {
scanf("%d%d", &QAQ[i].x, &QAQ[i].y);
cal(QAQ[i].x, QAQ[i].y);
if(QAQ[i].x < || QAQ[i].y < || QAQ[i].x > Ex || QAQ[i].y > Ey) {/////不合法的步数筛掉
n --; i --;
}
}
QAQ[++n].x = Ex, QAQ[n].y = Ey;
sort(QAQ + , QAQ + + n, cmp); init(); for(int i = ; i <= n; i ++) {
f[i] = C(QAQ[i].x + QAQ[i].y, QAQ[i].x);
if(f[i] == ) continue;
for(int j = ; j < i; j ++) {
f[i] -= (f[j] * C(QAQ[i].x - QAQ[j].x + QAQ[i].y - QAQ[j].y, QAQ[i].x - QAQ[j].x)) % mod;/////容斥
f[i] = (f[i] % mod + mod) % mod;
}
}
printf("%lld", f[n]);
return ;
}

【BZOJ】4767: 两双手【组合数学】【容斥】【DP】的更多相关文章

  1. BZOJ.4767.两双手(组合 容斥 DP)

    题目链接 \(Description\) 棋盘上\((0,0)\)处有一个棋子.棋子只有两种走法,分别对应向量\((A_x,A_y),(B_x,B_y)\).同时棋盘上有\(n\)个障碍点\((x_i ...

  2. bzoj 4767: 两双手 组合 容斥

    题目链接 bzoj4767: 两双手 题解 不共线向量构成一组基底 对于每个点\((X,Y)\)构成的向量拆分 也就是对于方程组 $Ax * x + Bx * y = X $ \(Ay * x + B ...

  3. 2019.02.11 bzoj4767: 两双手(组合数学+容斥dp)

    传送门 题意简述:你要从(0,0)(0,0)(0,0)走到(ex,ey)(ex,ey)(ex,ey),每次可以从(x,y)(x,y)(x,y)走到(x+ax,y+ay)(x+ax,y+ay)(x+ax ...

  4. bzoj 4767 两双手 - 动态规划 - 容斥原理

    题目传送门 传送门I 传送门II 题目大意 一个无限大的棋盘上有一只马,设马在某个时刻的位置为$(x, y)$, 每次移动可以将马移动到$(x + A_x, y + A_y)$或者$(x + B_x, ...

  5. BZOJ 4767 两双手

    题解: 发现这种题目虽然可以想出来,但磕磕碰碰得想挺久的 根据数学可以知道组成方案是唯一的(集合) 然后发现每个使用的大小可能是接近n^2的 直接dp(n^4)是过不了的 那么先观察观察 我们可以把每 ...

  6. BZOJ 4767: 两双手 [DP 组合数]

    传送门 题意: 给你平面上两个向量,走到指定点,一些点不能经过,求方案数 煞笔提一开始被题面带偏了一直郁闷为什么方案不是无限 现在精简的题意.....不就是$bzoj3782$原题嘛,还不需要$Luc ...

  7. HDU 5794 A Simple Chess (容斥+DP+Lucas)

    A Simple Chess 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5794 Description There is a n×m board ...

  8. [CF1086E]Beautiful Matrix(容斥+DP+树状数组)

    给一个n*n的矩阵,保证:(1)每行都是一个排列 (2)每行每个位置和上一行对应位置不同.求这个矩阵在所有合法矩阵中字典序排第几.考虑类似数位DP的做法,枚举第几行开始不卡限制,那么显然之前的行都和题 ...

  9. 【BZOJ3622】已经没有什么好害怕的了 容斥+DP

    [BZOJ3622]已经没有什么好害怕的了 Description Input Output Sample Input 4 2 5 35 15 45 40 20 10 30 Sample Output ...

随机推荐

  1. AS中一些不经常用到的快捷键

    1 书签 添加/移除书签 Ctrl+shift+F11 展示书签 shift+F11 下一个书签  shift+加号 上一个书签  shift+减号 2 折叠/展开代码块 展开代码块  ctrl+加号 ...

  2. C#匿名函数与Lambda表达式

    Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数.在C#中的Linq中的大部分就是由扩展方法 ...

  3. 从一份配置清单详解 Nginx 服务器配置

      概述 在前面< Nginx 服务器开箱体验> 一文中我们从开箱到体验,感受了一下 Nginx 服务器的魅力.Nginx 是轻量级的高性能 Web 服务器,提供了诸如 HTTP 代理和反 ...

  4. Python2和Python3同时安装到Windows

    上月已经把Python2安装好了,安装目录和及其下的Scripts也在安装时添加到了环境变量PATH中,可以使用python命令执行程序. 安装包:python-2.7.14.amd64.msi(没有 ...

  5. @PrePersist

    @PrePersistpublic void prePersist() { updatedAt = new Timestamp(System.currentTimeMillis()); created ...

  6. 获取随机字符串的方法 GetRandomString

    方法1:推荐方便. System.Hash 单元 Memo1.Lines.Add(THash.GetRandomString(50)); 方法二(自己写的): function TStrApi.Sui ...

  7. SQL2008关于权限的解释

    在SQL2008中我自己创建的一个登录名,可是那个登录名只可以用来登录,对数据库的操作什么都不能,连读取数据库都不可以.因为权限不够,只要把登录名的属性打开点击“服务器角色”,把public和sysa ...

  8. python 删除前3天的文件

    一.需求分析 1. 删除前3天的文件 2.如果目录为空,也一并删除掉 如果使用shell脚本,一条命令就搞定了.干啥还要用python? 1. 因为需要记录一些日志,使用shell不好实现 2. 作为 ...

  9. GreenPlum学习笔记:基础知识

    一.介绍 GreenPlum分布式数据仓库,大规模并行计算技术. 无共享/MPP核心架构 Greenplum数据库软件将数据平均分布到系统的所有节点服务器上,所以节点存储每张表或表分区的部分行,所有数 ...

  10. 【剑指Offer面试题】 九度OJ1389:变态跳楼梯

    转自:http://www.myexception.cn/program/1973966.html 时间限制:1 秒内存限制:32 兆特殊判题:否提交:2331解决:1332 题目描述: 一只青蛙一次 ...