【CF708E】Student's Camp

题意:有一个n*m的网格,每一秒钟,所有左面没有格子的格子会有p的概率消失,右面没有格子的格子也会有p的概率消失,问你t秒钟后,整个网格的上边界和下边界仍然连通的概率是多少。

$n,m\le 1500,t\le 10^6$。

题解:首先我们可以预处理出c数组,c[i]表示t秒钟后左边恰有i个格子消失的概率,这个用组合数算一算即可。又因为每一行的本质是相同的,所以令某一行最终剩下的格子是[l,r]的概率就是c[l-1]*c[m-r]。

然后考虑一个naive的DP。f[i][l][r]表示第i行剩下的是[l,r],且第i行与上边界连通的概率。不难得到转移方程,并用前缀和优化可得:

$f[i][l][r]=(sr[i-1][m]-gr[i-1][l-1]-gl[i-1][r+1])\cdot c[l-1]\cdot c[r-m]$

其中$sr[i][r]=\sum\limits_{l=1}^rf[i][l][r],gr[i][r]=\sum\limits_{j=1}^rsr[i][j]$。

但是这个转移是$O(nm^2)$的,所以我们不能这么设状态。有一个套路:把f[i][l][r]换成fl[i][l]和fr[i][r]试试?

具体推导过程留给读者。时间复杂度$O(nm)$。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. typedef long long ll;
  7. const ll P=1000000007;
  8.  
  9. int n,m,t;
  10. ll p;
  11. ll ine[100010],jc[100010],jcc[100010],p1[100010],p2[100010];
  12. ll fr[2][1510],fl[2][1510],sr[2][1510],sl[2][1510],gl[2][1510],gr[2][1510],sc[1510],c[1510];
  13. inline ll pm(ll x,ll y)
  14. {
  15. ll z=1;
  16. while(y)
  17. {
  18. if(y&1) z=z*x%P;
  19. x=x*x%P,y>>=1;
  20. }
  21. return z;
  22. }
  23. inline ll C(int a,int b)
  24. {
  25. if(a<b) return 0;
  26. return jc[a]*jcc[b]%P*jcc[a-b]%P;
  27. }
  28. inline ll calc(int a)
  29. {
  30. return C(t,a)*p1[a]%P*p2[t-a]%P;
  31. }
  32.  
  33. int main()
  34. {
  35. ll a,b;
  36. int i,j,d=0;
  37. scanf("%d%d%lld%lld%d",&n,&m,&a,&b,&t),p=a*pm(b,P-2)%P;
  38. ine[0]=ine[1]=jc[0]=jc[1]=jcc[0]=jcc[1]=1;
  39. for(i=2;i<=t;i++) ine[i]=P-(P/i)*ine[P%i]%P,jc[i]=jc[i-1]*i%P,jcc[i]=jcc[i-1]*ine[i]%P;
  40. for(p1[0]=p2[0]=i=1;i<=t;i++) p1[i]=p1[i-1]*p%P,p2[i]=p2[i-1]*(1-p)%P;
  41. for(i=0;i<=m;i++) c[i]=calc(i);
  42. for(i=1;i<=m;i++)
  43. for(j=1;j<=i;j++) a=c[j-1]*c[m-i]%P,fr[0][i]=(fr[0][i]+a)%P,fl[0][j]=(fl[0][j]+a)%P;
  44. for(i=1;i<=m;i++) sr[0][i]=(sr[0][i-1]+fr[0][i])%P;
  45. for(i=m;i>=1;i--) sl[0][i]=(sl[0][i+1]+fl[0][i])%P;
  46. for(i=1;i<=m;i++) gr[0][i]=(gr[0][i-1]+sr[0][i]*c[i])%P;
  47. for(i=m;i>=1;i--) gl[0][i]=(gl[0][i+1]+sl[0][i]*c[m-i+1])%P;
  48. for(i=0;i<=m;i++) sc[i]=(sc[i-1]+c[i])%P;
  49. for(i=2;i<=n;i++)
  50. {
  51. d^=1;
  52. memset(fl[d],0,sizeof(fl[d])),memset(fr[d],0,sizeof(fr[d]));
  53. memset(sl[d],0,sizeof(sl[d])),memset(sr[d],0,sizeof(sr[d]));
  54. for(j=1;j<=m;j++)
  55. {
  56. fr[d][j]=c[m-j]*((sr[d^1][m]-sl[d^1][j+1])*sc[j-1]%P-gr[d^1][j-1])%P;
  57. fl[d][j]=c[j-1]*((sr[d^1][m]-sr[d^1][j-1])*sc[m-j]%P-gl[d^1][j+1])%P;
  58. }
  59. for(j=1;j<=m;j++) sr[d][j]=(sr[d][j-1]+fr[d][j])%P;
  60. for(j=m;j>=1;j--) sl[d][j]=(sl[d][j+1]+fl[d][j])%P;
  61. for(j=1;j<=m;j++) gr[d][j]=(gr[d][j-1]+sr[d][j]*c[j])%P;
  62. for(j=m;j>=1;j--) gl[d][j]=(gl[d][j+1]+sl[d][j]*c[m-j+1])%P;
  63. }
  64. printf("%lld",(sr[d][m]+P)%P);
  65. return 0;
  66. }

【CF708E】Student's Camp 组合数+动态规划的更多相关文章

  1. CF708E Student's Camp

    麻麻我会做*3100的计数了,我出息了 考虑朴素DP我们怎么做呢. 设\(f_{i,l,r}\)为第\(i\)层选择\(l,r\)的依旧不倒的概率. \(q(l,r)\)表示经历了\(k\)天后,存活 ...

  2. [CodeForces-708E]Student's Camp

    题目大意: 一个n*m的墙,被吹k天风,每块靠边的砖都有p的概率被吹掉. 如果上下两行没有直接相连的地方,我们则认为这一堵墙已经倒塌. 问最后墙不倒塌的概率(模意义). 思路: 动态规划. 用f[i] ...

  3. [Codeforces708E]Student's Camp

    Problem 一个n*m块砖的建筑,一共k天,每天风从两边吹,吹掉砖的概率为p,反之为1-p,求最终建筑没有倒塌的可能性(上层与下层有交集且每一层都有砖) Solution 首先,我们可以预处理出p ...

  4. Student's Camp CodeForces - 708E (dp,前缀和优化)

    大意: $n$行$m$列砖, 白天左侧边界每块砖有$p$概率被摧毁, 晚上右侧边界有$p$概率被摧毁, 求最后上下边界连通的概率. 记${dp}_{i,l,r}$为遍历到第$t$行时, 第$t$行砖块 ...

  5. Codeforces 708E - Student's Camp(前缀和优化 dp)

    Codeforces 题目传送门 & 洛谷题目传送门 神仙 *3100,%%% 首先容易注意到 \(\forall i\in[1,m]\),第 \(i\) 行剩余的砖块一定构成一个区间,设其为 ...

  6. ACM-自学之旅

    分类 知识清单 数据结构 链式前向星 树状数组 线段树 线段树的区间合并 基于ST表格的RMQ 图论 最近公共祖先 树的直径.树的重心与树的点分治 树的最小支配集,最小点覆盖与最大独立集 求无向连通图 ...

  7. 51nod 1118 机器人走方格 解题思路:动态规划 & 1119 机器人走方格 V2 解题思路:根据杨辉三角转化问题为组合数和求逆元问题

    51nod 1118 机器人走方格: 思路:这是一道简单题,很容易就看出用动态规划扫一遍就可以得到结果, 时间复杂度O(m*n).运算量1000*1000 = 1000000,很明显不会超时. 递推式 ...

  8. HDU1223 Order Count 动态规划 组合数

    动态规划+组合数+大数 #include<cstdio> #include<cstdlib> #include<iostream> #include<algo ...

  9. 【UOJ#275】组合数问题(卢卡斯定理,动态规划)

    [UOJ#275]组合数问题(卢卡斯定理,动态规划) 题面 UOJ 题解 数据范围很大,并且涉及的是求值,没法用矩阵乘法考虑. 发现\(k\)的限制是,\(k\)是一个质数,那么在大组合数模小质数的情 ...

随机推荐

  1. 软件设计模式之模板方法模式(JAVA)

    什么是模板方法模式? 定义一个操作中算法的骨架,而将这些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 好抽象的概念啊,文绉绉的东西就是不讨人喜欢,下面我 ...

  2. Single Pattern(单例模式)

    单例模式是一种常用的软件设计模式.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在系统中某个类的实例只能存在一个,单例模式是最好的 ...

  3. Windows上使用sqlite3

    安装 去官网http://www.sqlite.org/download.html下载Windows下安装包,下载后,解压,设置环境变量 例如放在D:\sqlite3下,将D:\sqlite3加入环境 ...

  4. MySQL的sql_mode解析与设置,sql文件导入报错解决

    在往MySQL数据库中插入一组数据时,出错了!数据库无情了给我报了个错误:ERROR 1365(22012):Division by 0:意思是说:你不可以往数据库中插入一个 除数为0的运算的结果.于 ...

  5. linux环境中安装ftp服务

    需求说明: 今天项目中有一个新的需求,需要在linux环境中搭建一个ftp服务,在此记录下. 操作过程: 1.通过yum的方式安装ftp服务对应的软件包 [root@testvm01 ~]# yum ...

  6. js合并.css合并工具

    http://www.neoease.com/css-javascript-combo-tool/ http://www.neoease.com/minimize-javascript-files-u ...

  7. [Module] 03 - Software Design and Architecture

    本篇涉及内容: ORM框架(无需再用contentprovider或者sqlitedatebasehelper之类的古董工具了) 规划各种业务Bean文件(配合ORM框架) 设计一个好的请求基类(Ba ...

  8. 【Oracle】强制关闭会话

    select sid, serial# from V$session where sid in (select sid from v$LOCK where TYPE in ('TM','TX')); ...

  9. SQL利用CASE按分组显示合计

    按行显示的合计 select game, sum(purchase) as purchase_sum from purchase group by game; 按列显示的合计 select sum(c ...

  10. DBA操作

    sqlplus sys/tiger  as sysdba; alter user scott account unlock; 用户已更改 切换用户:conn scott/tiger as sysdba ...