[Codeforces708E]Student's Camp
Problem
一个n*m块砖的建筑,一共k天,每天风从两边吹,吹掉砖的概率为p,反之为1-p,求最终建筑没有倒塌的可能性(上层与下层有交集且每一层都有砖)
Solution
首先,我们可以预处理出pl[]和pr[]数组,表示k天后左右两边风吹到的位置的可能性
然后我们可以枚举层数,当前这一层的左右端点和上一层的左右端点,如果有公共部分则转移
这样的时间复杂度是O(n^5),显然我们可以用前缀和来优化:
引入f[i][r]+=dp[i][l][r](l <= r),再用一个sumr数组维护f数组的前缀和(suml数组是和sumr对称的)
那么dp[i][l][r]就等于总概率减去上一层区间在这个区间左边的概率和上一层区间在这个区间右边的概率(不相交的概率)
这样时间复杂度就降为了O(n2),我们再考虑优化使得时间复杂度降为O(n2):
我们再把dp降为两维,表示第i层最右边是j的概率
dp[i][j]=pl[l]pr[r](sumr[i-1][m] - suml[i-1][r+1] - sumr[i-1][l-1])
我们发现当l改变时,dp[i][j]改变的是可以再用前缀和维护的
于是时间复杂度变成了O(n^2)
Notice
前缀和预处理较多
Code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define sqz main
#define ll long long
#define reg register int
#define rep(i, a, b) for (reg i = a; i <= b; i++)
#define per(i, a, b) for (reg i = a; i >= b; i--)
#define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
const int INF = 1e9, mo = INF + 7, N = 1505, K = 100005;
const double eps = 1e-6, phi = acos(-1.0);
ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
ll p1[K], p2[K];
ll dp[N][N], suml[N][N], sumr[N][N], sum1[N], sum2[N], tt[K], pl[N], pr[N];
ll quickmo(ll x, int y)
{
ll ans = 1;
while (y)
{
if (y & 1) ans = ans * x % mo;
x = x * x % mo;
y /= 2;
}
return ans;
}
ll C(int n, int m)
{
return tt[m] * quickmo(tt[m - n], mo - 2) % mo * quickmo(tt[n], mo - 2) % mo;
}
int sqz()
{
int n = read(), m = read();
ll a = read(), b = read();
int k = read();
p1[0] = 1, p1[1] = a * quickmo(b, mo - 2) % mo;
p2[0] = 1, p2[1] = (b - a) * quickmo(b, mo - 2) % mo;
rep(i, 2, k) p1[i] = p1[i - 1] * p1[1] % mo, p2[i] = p2[i - 1] * p2[1] % mo;
tt[0] = 1;
rep(i, 1, k) tt[i] = tt[i - 1] * i % mo;
rep(i, 0, m - 1)
{
if (i > k) pl[i + 1] = 0;
else pl[i + 1] = C(i, k) * p1[i] % mo * p2[k - i] % mo;
pr[m - i] = pl[i + 1];
}
rep(i, 1, m) sum1[i] = (sum1[i - 1] + pl[i]) % mo;
sumr[0][m] = 1;
rep(i, 1, n)
{
rep(j, 1, m) sum2[j] = (sum2[j - 1] + pl[j] * sumr[i - 1][j - 1]) % mo;
rep(j, 1, m) dp[i][j] = (pr[j] * (sumr[i - 1][m] - suml[i - 1][j + 1]) % mo * sum1[j] % mo - pr[j] * sum2[j] % mo + mo) % mo;
rep(j, 1, m) suml[i][m - j + 1] = sumr[i][j] = (sumr[i][j - 1] + dp[i][j]) % mo;
}
printf("%lld\n", (sumr[n][m] + mo) % mo);
}
[Codeforces708E]Student's Camp的更多相关文章
- [CodeForces-708E]Student's Camp
题目大意: 一个n*m的墙,被吹k天风,每块靠边的砖都有p的概率被吹掉. 如果上下两行没有直接相连的地方,我们则认为这一堵墙已经倒塌. 问最后墙不倒塌的概率(模意义). 思路: 动态规划. 用f[i] ...
- 【CF708E】Student's Camp 组合数+动态规划
[CF708E]Student's Camp 题意:有一个n*m的网格,每一秒钟,所有左面没有格子的格子会有p的概率消失,右面没有格子的格子也会有p的概率消失,问你t秒钟后,整个网格的上边界和下边界仍 ...
- Student's Camp CodeForces - 708E (dp,前缀和优化)
大意: $n$行$m$列砖, 白天左侧边界每块砖有$p$概率被摧毁, 晚上右侧边界有$p$概率被摧毁, 求最后上下边界连通的概率. 记${dp}_{i,l,r}$为遍历到第$t$行时, 第$t$行砖块 ...
- CF708E Student's Camp
麻麻我会做*3100的计数了,我出息了 考虑朴素DP我们怎么做呢. 设\(f_{i,l,r}\)为第\(i\)层选择\(l,r\)的依旧不倒的概率. \(q(l,r)\)表示经历了\(k\)天后,存活 ...
- Codeforces 708E - Student's Camp(前缀和优化 dp)
Codeforces 题目传送门 & 洛谷题目传送门 神仙 *3100,%%% 首先容易注意到 \(\forall i\in[1,m]\),第 \(i\) 行剩余的砖块一定构成一个区间,设其为 ...
- Codeforces Round #588 (Div. 2) D. Marcin and Training Camp(思维)
链接: https://codeforces.com/contest/1230/problem/D 题意: Marcin is a coach in his university. There are ...
- java.io.NotSerializableException: test.io.file.Student
java.io.NotSerializableException: test.io.file.Student at java.io.ObjectOutputStream.writeObject0 ...
- 使用java反射机制编写Student类并保存
定义Student类 package org; public class Student { private String _name = null; ; ; public Student() { } ...
- 参加MVP OpenDay 和2015 MVP Community Camp社区大课堂
微软MVP Openday 1月30日在北京召开,到时全国上百位 MVP 专家将齐聚北京.当然还有亚太的其他国家地区的MVP 也会来北京,1月31日微软 MVP 项目组主办的年度微软技术社区分享大会- ...
随机推荐
- Android JNI 传递对象
JNI初步入门后,在传递数据的时候,遇到一个需求:有多个数据需要在Java与C代码之间进行传递.如果都做为函数参数传入,则函数很长很难看,并且多个数据的返回也不好实现.所以想到了把数据打包后传递.这在 ...
- DAY5 基本数据类型及内置方法
一.可变与不可变数据类型 1.可变类型:值改变,但是id不变,证明就是在改变原值,是可变类型 2.不可变类型:值改变,但是id也跟着变,证明是产生了新的值,是不可变类型 二.数字类型 1.整型int ...
- AD中的library中有些文件的后缀有.intlib .schlib .pcblib 这些都是库文件,但有什么区别呢?
intlib 是集成原理图和PCB封装的 schlib .只有原理图 pcblib 只有PCB封装 参考资料 1 https://zhidao.baidu.com/question/259298801 ...
- AtCoder Grand Contest 025 B - RGB Coloring
B - RGB Coloring 求ax + by = k (0<=x<=n && 0<=y<=n)的方案数,最后乘上C(n, x)*C(n,y) 代码: #i ...
- Java用FutureTask实现又返回值的线程
要实现有返回值的多线程,具体代码如下: package thread; import java.util.concurrent.Callable; import java.util.concurren ...
- 一款好用的取色工具TakeColor
简介:TakeColor,一款还算好用的取色软件,一个很小很简洁的exe文件,无需安装 使用:打开exe文件后,使用“Alt + C” 组合键即可在鼠标悬停的位置上获取到颜色值,可以获取HTML.RG ...
- caffe-ssd
1.安装依赖 1 sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-ser ...
- linux基础3
vim编辑器 vim 操作命令 在命令模式下操作 pageup 往上翻页(重要指数****) pagedown 往下翻页(重要指数****) H 移动到屏幕首行 gg 移动光标到文档的首行(重要指数* ...
- LOJ6036编码
每个串拆成两个,都插入trie数. 把trie树建出来后,每一条从根到叶子的链上最多只能有一个变量为1. 这是个经典的前后缀优化2-sat建图的套路. 树上的做法也就是边dfs边做而已. #inclu ...
- Linux 权限管理命令
第四章(二)权限管理命令 Linux常用命令(二)权限管理命令