模拟赛考过的题

当时太菜了现在也一样只拿到了$ 30$分

回来填个坑

LOJ #6374


题意

你要从$ (0,0)$走到$ (T_x,T_y)$,每次移动的坐标增量满足$ 0 \leq \Delta x \leq M_x,0 \leq \Delta y \leq M_y$

不允许原地不动,且存在$ k$个坐标增量$ (k_i,k_i)$不能移动

求恰好$ R$步走到终点的方案数,对$ 1e9+7$取模

数据范围有$ T_x,T_y \leq 10^6,k \leq 50,R \leq 1000 $

保证所有$ k_i$均为$ G$的倍数且$ 10000 \leq G \leq 50000$


$ Solution$

先考虑没有$ k$的限制怎么做

容易发现坐标两维是很独立的

尝试把它们分开来做

用$ calc(x,y,z)$表示走$ z$步,每步走的距离$ \in [0,y]$,走到$ x$的方案数

直接$ DP$复杂度过大,尝试用容斥优化这个东西

设$ g(i)$表示至少有$i$步超出限制的情况

我们找出$ i$步让他们均移动$ y+1$的距离,然后剩下的没有限制,用插板法计算

$ g(i)=\binom{z}{i}·\binom{x-(y+1)*i+z-1}{z-1}$

然后根据套路容斥得

$ calc(x,y,z)=\sum\limits_{i=0}^{limit} (-1)^ig(i)$

(貌似这里可以看成二项式反演中$ \binom{n}{0}=1$的特殊情况)

这样单次计算的复杂度是$ O(R)$的

容易发现这两维并不完全独立

因为两维不允许均原地不动的情况出现

即这样算出来的$ calc(T_x,M_x,R)*calc(T_y,M_y,R)$其实是走了至多$ R$步的方案数

按照套路二项式反演

设$ g(i)$表示走了至多$ i$步的方案数,$ f(i)$表示恰好走了$ i$步的方案数

$ g(R)=calc(T_x,M_x,R)*calc(T_y,M_y,R)=\sum\limits_{i=0}^R\binom{R}{i}f(i)$

反演得

$ f(R)=\sum\limits_{i=0}^n (-1)^{n-i}\binom{R}{i}g(i)$

这样就解决了没有$ k$的情况

时间复杂度$ O(R^2)$

然后再考虑有$ k$条限制的情况(每条限制可以多次违反,注意去重!)

依旧考虑容斥

设$ g(i)$表示至少违反了$ i$条限制的方案数,$ f(i)$表示恰好违反了$ i$条限制的方案数

显然我们需要计算的是$ f(0)=\sum\limits_{i=0}^{limit} (-1)^i g(i)$

现在问题是$ g(i)$如何计算

我们设$ F(x,y)$表示违反了$ x$条限制,这些限制的$ k_i$之和为$ y*G$的方案数

显然$ DP$的第二维不超过$ \frac{10^6}{10^4}=100$,因此可以非常轻易的计算出$ DP$的结果

然后发现$ limit$也并不大,直接利用$ F$数组计算$ g$数组的值并计算即可

理论复杂度可能高达$ 1000*1000*100*100$

但由于内层可以记忆化,复杂度能去掉一个$ 1000$

再加上数据极度不满,这个算法跑的飞快

就解决了这道题


$ my \ code$

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define p 1000000007
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,Tx,Ty,Mx,My,R,G;
int a[],g[];
int jc[],njc[],inv[];
int C(int x,int y){return 1ll*jc[x]*njc[y]%p*njc[x-y]%p;}
int calc(int x,int y,int bs){//每步不超过y,走的距离为x,走了bs步
if(y*bs<x)return ;int ans=;
for(rt i=,fla=;i<=bs&&(y+)*i<=x;i++,fla*=-)
(ans+=1ll*fla*C(bs,i)*C(x-(y+)*i+bs-,bs-)%p)%=p;
return ans;
}
int anss[][],ans2[][];
int solve(int x,int R){
int ans=;
for(rt i=R,fla=;i>=;i--,fla*=-){
int v;
if(anss[x/G][i])v=anss[x/G][i];else v=1ll*calc(Tx-x,Mx,i)*calc(Ty-x,My,i)%p;
anss[x/G][i]=v;
(ans+=1ll*v*C(R,i)*fla%p)%=p;
}
return (ans+p)%p;
}
int F[][];//F[i][j]走i步走出i*G的方案数
int main(){
jc[]=jc[]=njc[]=njc[]=inv[]=inv[]=;
Tx=read(),Ty=read(),Mx=read(),My=read();
R=read();G=read();k=read();
for(rt i=;i<=max(Tx,Ty)+R;i++){
jc[i]=1ll*jc[i-]*i%p;
inv[i]=1ll*inv[p%i]*(p-p/i)%p;
njc[i]=1ll*njc[i-]*inv[i]%p;
}
if(!k)return write(solve(,R)),;
for(rt i=;i<=k;i++)a[i]=read();
sort(a+,a+k+);k=unique(a+,a+k+)-a-; F[][]=;
g[]+=solve(,R);
for(rt i=;i*G<=min(Tx,Ty);i++)
for(rt j=;j*G<=min(Tx,Ty);j++){
for(rt d=;d<=k;d++)if(a[d]<=min(Tx,Ty)&&a[d]<=j*G)
(F[i][j]+=F[i-][j-a[d]/G])%=p;
(g[i]+=1ll*solve(j*G,R-i)*F[i][j]%p)%=p;
}
ll ret=;
for(rt i=,fla=;i*G<=min(Tx,Ty);i++,fla*=-)(ret+=1ll*fla*g[i]*C(R,i)%p)%=p;
cout<<(ret+p)%p;
return ;
}

LOJ #6374「SDWC2018 Day1」网格的更多相关文章

  1. 「SDWC2018 Day1」网格

    题目当中有三条限制,我们来逐一考虑.对于第一条限制,每次走动的增加量 \(x_i \le M_x, y_i \le M_y\),可以发现一共走的步数是确定的,那么就相当于解这样两个方程组: \[x_1 ...

  2. LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)

    LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...

  3. Loj #2495. 「AHOI / HNOI2018」转盘

    Loj #2495. 「AHOI / HNOI2018」转盘 题目描述 一次小 G 和小 H 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1 ...

  4. Loj #2494. 「AHOI / HNOI2018」寻宝游戏

    Loj #2494. 「AHOI / HNOI2018」寻宝游戏 题目描述 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得 ...

  5. loj#2020 「AHOI / HNOI2017」礼物 ntt

    loj#2020 「AHOI / HNOI2017」礼物 链接 bzoj没\(letex\),差评 loj luogu 思路 最小化\(\sum\limits_1^n(a_i-b_i)^2\) 设改变 ...

  6. LOJ #2802. 「CCC 2018」平衡树(整除分块 + dp)

    题面 LOJ #2802. 「CCC 2018」平衡树 题面有点难看...请认真阅读理解题意. 转化后就是,给你一个数 \(N\) ,每次选择一个 \(k \in [2, N]\) 将 \(N\) 变 ...

  7. LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)

    题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...

  8. LOJ #2540. 「PKUWC 2018」随机算法(概率dp)

    题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...

  9. LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)

    Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...

随机推荐

  1. 【洛谷P1507 NASA的食物计划】

    题目背景 NASA(美国航空航天局)因为航天飞机的隔热瓦等其他安全技术问题一直大伤脑筋,因此在各方压力下终止了航天飞机的历史,但是此类事情会不会在以后发生,谁也无法保证,在遇到这类航天问题时,解决方法 ...

  2. 跟我一起写一个hello-world react组件并发布到npm

    第一步:初始化我们的配置 $ mkdir react-hello-world $ cd react-hello-world/ $ npm init -y 修改我们的package.json文件 //p ...

  3. strutrs contextMap

    contextMap(非常重要) 1.动作类的生命周期 明确:动作类是多例的,每次动作访问,动作类都会实例化.所以是线程安全的.与Struts1的区别是,struts1的动作类是单例的. 2.请求动作 ...

  4. http uri唯一标识

    URI:唯一标识并且信息资源(简单理解为:发邮件的地址,身份证号).uri包括url 比如通过查找一个uri,找到一张图片“https://timgsa.baidu.com/timg?image&am ...

  5. day13-(事务&mvc&反射补充)

    回顾: jsp: java服务器页面 jsp的脚本 jsp的注释 html注释 java注释 jsp注释 <%-- --%> jsp的指令 page:声明页面一些属性 重要的属性: imp ...

  6. 黑苹果是否会成为mac电脑的竞争对手?

    最近黑科技技术大佬们都在传扬windows系统上安装mac系统,不用买mac电脑也可以使用mac一样的操作环境.什么是黑苹果?一起来看看如何在windows系统上安装mac系统. 更多专题,可关注小编 ...

  7. 三台机器之间ssh互信配置

    三台机器之间ssh互信配置 环境介绍:192.168.65.128    my1-222192.168.65.129  my2-223192.168.65.130    web224 # 步骤一:# ...

  8. 关于Navicat远程连接远程服务器的mysql 报错问题

    我们连接远程服务器的mysql,如果出现问题,很大问题会出在服务器的端口和授权问题 首先我们通过 1:netstat -an|grep 3306 来查看mysql默认的端口3306是否开启,允许哪个i ...

  9. [ZJOI2007]棋盘制作 悬线法dp 求限制下的最大子矩阵

    https://www.luogu.org/problemnew/show/P1169 第一次听说到这种dp的名称叫做悬线法,听起来好厉害 题意是求一个矩阵内的最大01交错子矩阵,开始想的是dp[20 ...

  10. ContentType组件

    django提供的一个快速连表操作的组件 适用于:一个字段确定不了唯一: 如:pricepolicy表中,course_id和content_type中对应的课程类型id才能确定唯一: model.p ...