CodeForces 559C Gerald and Gia

大致题意:有一个 $ N\times M $ 的网格,其中有些格子是黑色的,现在需要求出从左上角到右下角不经过黑色格子的方案数(模 $ 10^9+7 $ )



$ solution: $

首先 $ orz $ 鸽王,看一眼就说:“嗯?这不就是一道格路+容斥的小水题吗?”,然后秒切大火题。

这道题主要考验我们如何设置动态规划的状态以保证不重不漏的算好所有情况。上一次我发这类“找基准点”的DP题解应该是POJ 1737 Connected Graph 这两道题都要求我们要精确的计算所有情况,我们都需要去构思一种可以囊括所有情况且不会重复的方案。

这一题首先讲一个基本知识:在一个 $ N\times M $ 的网格里,从左上角到右下角的方案数就是: $ C^{N-1}_{N+M-2} $ ,这个可以很好理解:我们从左上角走到右下角总共会走 $ N+M-2 $ 步,而我们只需要在这些步数里选择有那几步是向下走的即可。然后我们回来分析题目,这道题我们很难直接算,只能循序渐进,也就是用最优子结构来得出最优答案,而且这是完全没有后效性的。但是如果我们将从左上角到每一个格子的方案都求出来,这道题的数据范围就很不友好。不过我们发现它的黑色格子数目很少,于是我们可以反向思考,我们求出它会走过黑色格子的路径,这样就不会去跑一些没用的状态了。我们将黑色格子按照从左上角到右下角的顺序排序,然后以到每一个黑色格子的路径作为状态。但是这样我们发现会严重重复,所以我们必须想办法不重复。

为了不重复我们要顶一个基准点:就是这条路径到达的第一个黑色格子,我们只需要确定这第一个格子接下来的路随便走都没问题,于是我们要求出左上角到每一个黑色格子的不经过其他节点的路径(这不就是一个子问题吗?)于是问题迎刃而解。因为我们有办法求所有的经过黑色格子的路径进而反向得出不经过任何黑色格子的路径数。



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define rg register int using namespace std; const int mod=1e9+7; int h,w,n;
int f[2005];
int jc[200015];
int inv[200015]; struct su{
int x,y;
inline bool operator <(su z){
return x!=z.x?x<z.x:y<z.y;
}
}a[2005]; inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar())) if(ch=='-')sign=1;
while(isdigit(ch)) res=res*10+(ch^48),ch=getchar();
return sign?-res:res;
} inline int C(int x,int y){
return (ll)jc[x]*inv[x-y]%mod*inv[y]%mod;
} inline int ksm(ll x,int y){
rg res=1;
while(y){
if(y&1)res=res*x%mod;
x=x*x%mod; y>>=1;
}return res;
} int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
h=qr(); w=qr(); n=qr();
jc[0]=jc[1]=inv[0]=1; rg tot=h+w+1;
for(rg i=2;i<=tot;++i)
jc[i]=(ll)jc[i-1]*i%mod;
inv[tot]=ksm(jc[tot],mod-2);
for(rg i=tot;i>1;--i)
inv[i-1]=(ll)inv[i]*i%mod;
for(rg i=1;i<=n;++i)
a[i].x=qr(),a[i].y=qr();
a[n+1].x=h; a[n+1].y=w; sort(a+1,a+n+2);
for(rg i=1;i<=n+1;++i){
f[i]=C(a[i].x+a[i].y-2,a[i].x-1);
for(rg j=1;j<i;++j){
if(a[i].x<a[j].x||a[i].y<a[j].y)continue;
f[i]=(f[i]-(ll)f[j]*C(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x))%mod;
}
}printf("%d\n",(f[n+1]+mod)%mod);
return 0;
}

CodeForces 559C Gerald and Gia (格路+容斥+DP)的更多相关文章

  1. 【题解】CF559C C. Gerald and Giant Chess(容斥+格路问题)

    [题解]CF559C C. Gerald and Giant Chess(容斥+格路问题) 55336399 Practice: Winlere 559C - 22 GNU C++11 Accepte ...

  2. 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 ...

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

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

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

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

  5. $bzoj2560$ 串珠子 容斥+$dp$

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

  6. Codeforces 1553I - Stairs(分治 NTT+容斥)

    Codeforces 题面传送门 & 洛谷题面传送门 u1s1 感觉这道题放到 D1+D2 里作为 5250 分的 I 有点偏简单了吧 首先一件非常显然的事情是,如果我们已知了排列对应的阶梯序 ...

  7. codeforces B. Friends and Presents(二分+容斥)

    题意:从1....v这些数中找到c1个数不能被x整除,c2个数不能被y整除! 并且这c1个数和这c2个数没有相同的!给定c1, c2, x, y, 求最小的v的值! 思路: 二分+容斥,二分找到v的值 ...

  8. Codeforces 439E Devu and Birthday Celebration 容斥

    Devu and Birthday Celebration 我们发现不合法的整除因子在 m 的因子里面, 然后枚举m的因子暴力容斥, 或者用莫比乌斯系数容斥. #include<bits/std ...

  9. Codeforces.997C.Sky Full of Stars(容斥 计数)

    题目链接 那场完整的Div2(Div1 ABC)在这儿.. \(Description\) 给定\(n(n\leq 10^6)\),用三种颜色染有\(n\times n\)个格子的矩形,求至少有一行或 ...

随机推荐

  1. 【Luogu】P1850换教室(期望DP)

    题目链接 又一道面向题解编程的恶心神题.真是叫人质壁分离…… 设f[i][j][k]表示考虑了前i节课,尝试了j次,当前申请结果为k时消耗的体力值. 对于f[i][j][0]有两种情况:一是我们的主角 ...

  2. P1582 倒水 (二进制)

    题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒 ...

  3. ElasticSearch API 之 DELETE

    删除API,可以根据特定的ID删除文档. $ curl -XDELETE 'http://localhost:9200/website/blog/AVbkih8AltSLRRB7XAun' 会返回下面 ...

  4. 【Vim命令大全】史上最全的Vim命令

    曾经使用了两年多的Vim,手册也翻过一遍.虽然现在不怎么用vim了,曾经的笔记还是贴出来,与喜欢vim的朋友分享. 1. 关于Vim vim是我最喜欢的编辑器,也是linux下第二强大的编辑器. 虽然 ...

  5. iOS推送的开启与关闭

    开启: 
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationType ...

  6. centos7 搭建hadoop

    参考文档:http://blog.csdn.net/xiaoxiangzi222/article/details/52757168 https://waylau.com/centos-7-instal ...

  7. android 布局之LinearLayout(学习一)

    一,View localView = mRadioGroup_content.getChildAt(i);指定自定义菜单栏的点击格,如child3 其中:mRadioGroup_content = ( ...

  8. fmt 包中的函数和方法

    / Fprintf 将参数列表 a 填写到格式字符串 format 的占位符中// 并将填写后的结果写入 w 中,返回写入的字节数func Fprintf(w io.Writer, format st ...

  9. Java并发编程,深入理解ReentrantLock

    ReentrantLock简介 ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁, 支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次 ...

  10. 洛谷 P1034 矩形覆盖

    P1034 矩形覆盖 题目描述 在平面上有nn个点(n \le 50n≤50),每个点用一对整数坐标表示.例如:当 n=4n=4 时,44个点的坐标分另为:p_1p1​(1,11,1),p_2p2​( ...