题目链接

\(Description\)

棋盘上\((0,0)\)处有一个棋子。棋子只有两种走法,分别对应向量\((A_x,A_y),(B_x,B_y)\)。同时棋盘上有\(n\)个障碍点\((x_i,y_i)\),棋子在任何时刻都不能跳到障碍点。

求棋子从\((0,0)\)跳到\((E_x,E_y)\)的方案数。答案对\(10^9+7\)取模。

\(Solution\)

注意到\(A_x*B_y-A_y*B_x\neq0\),即两向量不共线,从某个点走到另一个点,两种方式分别所用次数\(x,y\)是确定的。即求该方程组的非负整数解:$$\left{\begin{array}{lr}A_xx+B_xy=X_i\A_yx+B_yy=Y_i\end{array}\right.$$

同网格图方案数,从某个点以两种方式分别走\(x,y\)步到达另一个点,这样的方案数为\(\binom{x+y}{x}\)。

将每个点表示成这样的\(x,y\)(从\((0,0)\)出发到达该点两种方式分别所需步数)后,任意两点所需的步数就是\(x_i-x_j,y_i-y_j\)了。方案数同样可以用组合数求。

然后就可以排序后容斥了。

\(f(i)\)表示在\(i\)之前不经过任何障碍点,到达障碍点\(i\)的方案数。记\(cnt(i,j)\)表示从障碍点\(i\)到\(j\)的方案数。将起点视为障碍点\(0\),那么$$f(i)=cnt(0,i)-\sum_{j=1}^{i-1}f(j)*cnt(j,i)$$

将终点视为第\(n+1\)个障碍点,答案就是\(f(n+1)\)了。

复杂度\(O(n^2)\)。

因为\(A_x,A_y,B_x,B_y\)可能有负数,所以要走的步数是\(n^2\)级别的(比如\((1,0),(-500,1)\))。组合数要\(n+m\)所以上界要到\(2n^2\)。

//4736kb	448ms 为啥这么慢呢
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define mod 1000000007
typedef long long LL;
const int N=505,M=500000; int Ax,Ay,Bx,By,f[N],fac[M+2],ifac[M+2];
struct Point
{
int x,y;
bool operator <(const Point &a)const{
return x==a.x?y<a.y:x<a.x;
}
}p[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline int FP(int x,int k)
{
int t=1;
for(; k; k>>=1,x=1ll*x*x%mod)
if(k&1) t=1ll*t*x%mod;
return t;
}
void Calc(int yi,int xi,int &x,int &y)
{
int a=xi*By-yi*Bx,b=Ax*By-Ay*Bx;
if(!b||a%b) {x=-1; return;}//判0。。
int c=xi*Ay-yi*Ax,d=Bx*Ay-By*Ax;
if(!d||c%d) {x=-1; return;}
x=a/b, y=c/d;
}
inline int C(int n,int m)
{
if(n<0||m<0) return 0;//return C(n+m,n)
return 1ll*fac[n+m]*ifac[n]%mod*ifac[m]%mod;
} int main()
{
fac[0]=fac[1]=1;
for(int i=2; i<=M; ++i) fac[i]=1ll*fac[i-1]*i%mod;
ifac[M]=FP(fac[M],mod-2);
for(int i=M-1; ~i; --i) ifac[i]=1ll*ifac[i+1]*(i+1)%mod; int Ex=read(),Ey=read(),n=read(),cnt=0;
Ax=read(), Ay=read(), Bx=read(), By=read(); Calc(Ey,Ex,Ex,Ey);
if(Ex<0||Ey<0) return puts("0"),0;
p[++cnt]=(Point){Ex,Ey}; for(int x,y; n--; )
{
Calc(read(),read(),x,y);
if(!(x<0||y<0||x>Ex||y>Ey)) p[++cnt]=(Point){x,y};//需要走更多步的不会相交(否则排序还出问题?)
}
n=cnt, std::sort(p+1,p+1+n); for(int i=1; i<=n; ++i)
{
Point now=p[i]; LL tmp=C(now.x,now.y);
if(!tmp) continue;
for(int j=1; j<i; ++j)
tmp+=mod-1ll*f[j]*C(now.x-p[j].x,now.y-p[j].y)%mod;
f[i]=(int)(tmp%mod);
}
printf("%d\n",f[n]); return 0;
}

BZOJ.4767.两双手(组合 容斥 DP)的更多相关文章

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

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

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

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

  3. BZOJ 4767 两双手

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

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

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

  5. 【BZOJ】4767: 两双手【组合数学】【容斥】【DP】

    4767: 两双手 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1057  Solved: 318[Submit][Status][Discuss] ...

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

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

  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. $bzoj2560$ 串珠子 容斥+$dp$

    正解:容斥+$dp$ 解题报告: 传送门$QwQ$ $umm$虽然题目蛮简练的了但还是有点难理解,,,我再抽象一点儿,就说有$n$个点,点$i$和点$j$之间有$a_{i,j}$条无向边可以连,问有多 ...

随机推荐

  1. numpy 中 shape_base提供的tile方法

    tile函数 来自于numpy.lib.shape_base 功能:重复某个数组. 比如说tile(A, n), 功能是将数组A重复n次,构成一个新的数组(行数只有1个) 比如说tile(A, n, ...

  2. 『转载』hadoop 1.X到2.X的变化

    表1新旧hadoop脚本/变量/位置变化表 改变项 原框架中 新框架中(Yarn) 备注 配置文件位置 ${hadoop_home_dir}/conf ${hadoop_home_dir}/etc/h ...

  3. 开源监控系统整合Nagios+Cacti+Nconf详解

    1.配置好yum源,为了提高效率建议搭建本地yum源 yum install -y http*  yum install -y mysql*  yum install -y php-*  yum in ...

  4. unicode-range特定字符使用font-face自定义字体

    链接: https://www.zhangxinxu.com/wordpress/2016/11/css-unicode-range-character-font-face/

  5. AndroidStudio中builde.gradle文件详解

    Android Studio是采用Gradle来构建项目的,一个Android项目中包含两个build.gradle文件,如下图:     (1)最外层目录下build.gradle文件 最外层目录下 ...

  6. as 插件GsonFormat用法(json字符串快速生成javabean)

    GsonFormat 主要用于使用Gson库将JSONObject格式的String 解析成实体,该插件可以加快开发进度,使用非常方便,效率高. 插件地址:https://plugins.jetbra ...

  7. python3中的编解码

    #一个知识点是:python3中有两种字符串数据类型:str类型和 bytes类型:sty类型存储unicode数据,bytes类型存储bytes数据 #当我们在word上编辑文件的时候,数据保存之前 ...

  8. vue修饰符学习

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  9. HDU 3746 将字符串的全部字符最少循环2次需要添加的字符数

    Sample Input3aaaabcaabcde Sample Output025 题目大意:给你一个字符串,要求将字符串的全部字符最少循环2次需要添加的字符数.例子:abcabc 已经循环2次,添 ...

  10. 在django中使用FormView,success_url死活不能生效的问题

    真的不知道是怎么回事, 以前都是手动的, form使用modelform. view使用createview. 今天写新系统时,为了更灵活. form使用form,(这样一来,可以在form是随便按数 ...