BZOJ4767: 两双手【组合数学+容斥原理】
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分别表示两种单步移动的方法,保证AxBy-AyBx≠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
思路
首先发现可以算出来从起点到任何一个点的两次操作的步数
然后就转化成了路径计数问题,然后就可以套一个容斥
用\(dp_{i}\)表示从原点到i不经过任何黑点的方案数,这样就可以枚举从原点到现在的第一个经过的黑点所对应的方案数
然后就可以算了
注意算的时候不能把第一次或者第二次操作次数大于目标点的点算进去,不然会出锅
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pi;
const int Mod = 1e9 + 7;
const int N = 1e3 + 10;
const int M = 3e6 + 10;
int n, ex, ey, ax, ay, bx, by;
int inv[M], fac[M], dp[M];
pi p[N];
int add(int a, int b) {
return (a += b) >= Mod ? a - Mod : a;
}
int sub(int a, int b) {
return (a -= b) < 0 ? a + Mod : a;
}
int mul(int a, int b) {
return 1ll * a * b % Mod;
}
int fast_pow(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = mul(res, a);
b >>= 1;
a = mul(a, a);
}
return res;
}
int C(int a, int b) {
if (a < 0 || b < 0) return 0;
return mul(fac[a + b], mul(inv[b], inv[a]));
}
void init() {
fac[0] = inv[0] = 1;
for (int i = 1; i < M; i++) fac[i] = mul(fac[i - 1], i);
inv[M - 1] = fast_pow(fac[M - 1], Mod - 2);
for (int i = M - 2; i >= 1; i--) inv[i] = mul(inv[i + 1], i + 1);
}
pi calc(int x, int y) {
int a = -1, b = -1;
if ((x * by - y * bx) % (ax * by - ay * bx) == 0)
a = (x * by - y * bx) / (ax * by - ay * bx);
if ((x * ay - y * ax) % (bx * ay - by * ax) == 0)
b = (x * ay - y * ax) / (bx * ay - by * ax);
return pi(a, b);
}
int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
init();
scanf("%d %d %d %d %d %d %d", &ex, &ey, &n, &ax, &ay, &bx, &by);
int cnt = 0;
p[++cnt] = calc(ex, ey);
if (p[1].first < 0 || p[1].second < 0) {
puts("0");
return 0;
}
for (int i = 1; i <= n; i++) {
int u, v; scanf("%d %d", &u, &v);
pi cur = calc(u, v);
if (cur.first < 0 || cur.second < 0 || cur.first > p[1].first || cur.second > p[1].second) continue;
//需要特判 cur.first > p[1].first || cur.second > p[1].second
p[++cnt] = cur;
}
n = cnt;
sort(p + 1, p + cnt + 1);
n = unique(p + 1, p + cnt + 1) - p - 1;
for (int i = 1; i <= n; i++) {
dp[i] = C(p[i].first, p[i].second);
for (int j = 1; j < i; j++) {
dp[i] = sub(dp[i], mul(dp[j], C(p[i].first - p[j].first, p[i].second - p[j].second)));
}
}
printf("%d", dp[n]);
return 0;
}
BZOJ4767: 两双手【组合数学+容斥原理】的更多相关文章
- bzoj4767两双手 容斥+组合
4767: 两双手 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 684 Solved: 208[Submit][Status][Discuss] ...
- BZOJ4767 两双手(组合数学+容斥原理)
因为保证了两向量不共线,平面内任何一个向量都被这两个向量唯一表示.问题变为一张有障碍点的网格图由左上走到右下的方案数. 到达终点所需步数显然是平方级别的,没法直接递推.注意到障碍点数量很少,那么考虑容 ...
- 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 ...
- BZOJ4767 两双手
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- bzoj 4767 两双手 - 动态规划 - 容斥原理
题目传送门 传送门I 传送门II 题目大意 一个无限大的棋盘上有一只马,设马在某个时刻的位置为$(x, y)$, 每次移动可以将马移动到$(x + A_x, y + A_y)$或者$(x + B_x, ...
- bzoj 4767: 两双手 组合 容斥
题目链接 bzoj4767: 两双手 题解 不共线向量构成一组基底 对于每个点\((X,Y)\)构成的向量拆分 也就是对于方程组 $Ax * x + Bx * y = X $ \(Ay * x + B ...
- 【BZOJ】4767: 两双手【组合数学】【容斥】【DP】
4767: 两双手 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1057 Solved: 318[Submit][Status][Discuss] ...
- 【BZOJ4767】两双手(动态规划,容斥)
[BZOJ4767]两双手(动态规划,容斥) 题面 BZOJ 题解 发现走法只有两种,并且两维坐标都要走到对应的位置去. 显然对于每个确定的点,最多只有一种固定的跳跃次数能够到达这个点. 首先对于每个 ...
- BZOJ_3129_[Sdoi2013]方程_组合数学+容斥原理
BZOJ_3129_[Sdoi2013]方程_组合数学+容斥原理 Description 给定方程 X1+X2+. +Xn=M 我们对第l..N1个变量进行一些限制: Xl < = A ...
随机推荐
- Python - openpyxl 读写操作Excel
openpyxl特点 openpyxl(可读写excel表)专门处理Excel2007及以上版本产生的xlsx文件,xls和xlsx之间转换容易 注意:如果文字编码是“gb2312” 读取后就会显 ...
- 增加centos7.3上安装php7的php-soap扩展
代码传到正式服务器上去就:Class 'SoapClient' not found,只能是soap扩展没装! 因为服务器上面的PHP是7.1.11的,所以soap也要装7.1.11的,否则会冲突 ...
- English trip -- VC(情景课) 6 D
Read 阅读 Teresa‘s Day Treesa's is busy today. he meeting with her friend Joan is at 10:00. Her docto ...
- android--------Android Studio常见问题以及解决方式
gradle build的时候出现的问题: Error:Execution failed for task ':app:packageDebug'. Duplicate files copied in ...
- android--------WebView实现 Html5 视频标签加载
自Android 4.4起,Android中的WebView开始基于Chromium(谷歌浏览器)支持浏览器的一系列功能,webkit解析网页各个节点,这个改变,使得WebView的性能大幅度提升,并 ...
- 使用nginx+dnsmasq解决同IP不同端口Session冲突问题
由于一台服务器上需要部署多个项目,而我们的WEB项目因为用到框架都是一样的,导致同时运行,session相互冲突,这个登录后,那个就得重新登录,造成了使用不方便,原因是IP相同认为是同一个域,接收了B ...
- hdu1584
蜘蛛牌 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- Centos7 docker 常用指令
Docker 运行在 CentOS 7 上,要求系统为64位.系统内核版本为 3.10 以上 一.docker的安装及卸载 1.查看当前系统内核版本: [root@docker ~]# uname - ...
- darktrace 亮点是使用的无监督学习(贝叶斯网络、聚类、递归贝叶斯估计)发现未知威胁——使用无人监督 机器学习反而允许系统发现罕见的和以前看不见的威胁,这些威胁本身并不依赖 不完善的训练数据集。 学习正常数据,发现异常!
先说说他们的产品:企业免疫系统(基于异常发现来识别威胁) 可以看到是面向企业内部安全的! 优点整个网络拓扑的三维可视化企业威胁级别的实时全局概述智能地聚类异常泛频谱观测 - 高阶网络拓扑;特定群集,子 ...
- PHP:第四章——数组中的排序函数
<pre> <?php header("Content-Type:text/html;charset=utf-8"); //1) /*sort - 对数组进行升序 ...