【BZOJ4944】[NOI2017]泳池(线性常系数齐次递推,动态规划)

首先恰好为\(k\)很不好算,变为至少或者至多计算然后考虑容斥。

如果是至少的话,我们依然很难处理最大面积这个东西。所以考虑答案至多为\(k\)的概率,再减去至多为\(k-1\)的概率就是最终的答案。

发现要求的东西必须贴着底边,所以对于每一列而言我们需要考虑的就是选定区间的最低的那个不安全的格子的行号,再乘上底边的长度。

所以考虑设\(f[n]\)表示底边长度为\(n\)的答案,即确定底边长度为\(n\)时,面积小于等于\(k\)的答案。

那么我们有这样一个转移:

\[f[n]=\sum_{i=0}^{min(n,k)} f[n-i-1]\sum_{j=2}^{[\frac{k}{i}]+1}dp[i][j]
\]

翻译一下,首先我们枚举一下上一个在底边断开的位置,即上一次某一列的第一行就存在一个障碍,那么就可以知道这一次的底边长度是\(i\),前面符合条件的是\(f[n-i-1]\),然后枚举这一次的高度是多少,确定高度之后乘上在这个高度上至少存在一个障碍的概率即\(dp[i][j]\)值。

注意一下我们这里的模型,是每次考虑一段第一行不为障碍的东西,而分割的地方我们强制存在障碍,即我们考虑完了这一段之后强制在末尾放了一个障碍,所以答案是\(f[n+1]\),而末尾那个障碍是不需要放的,所以我们实际要求的东西是\(\frac{f[n+1]}{1-p}\),其中\(p\)是不是障碍的概率。

那么求出\(dp\)值之后,每次的系数就唯一确定了,转成线性常系数递推。

考虑怎么求解\(dp\)值。

显然这个\(dp\)值要做的就是找到一个位置使得其障碍高度恰好为\(j\),然后其他位置都不小于\(j\)。

那么我们考虑枚举最靠左侧的那个障碍的位置\(j\),那么它是障碍,所以概率是\(1-p\),而它下边的都不是障碍,所以概率是\(p^{j-1}\),,那么先枚举这个最靠左的位置是\(l\),那么我们就可以得到转移:

\[dp[i][j]=(1-p)p^{j-1}\sum_{l=1}^i (\sum_{k\gt j}dp[l-1][k])(\sum_{k\ge j}dp[i-l][k])
\]

即考虑其左右的位置,因为这个位置是最靠左的,所以左侧的最低的障碍一定都比这个位置的障碍要高,所以限制条件是\(k\gt j\),而右边无所谓,只要不比这里矮就行了,所以枚举的是\(k\ge j\)。

那么这个\(dp\)方程可以很容易的使用后缀和优化得到。

那么单次转移\(O(k)\),状态总数\(O(klogk)\),这是因为\(i*(j-1)\le k\),所以状态是调和级数级别的。所以这部分的\(dp\)的复杂度是\(O(k^2logk)\)。

接下来维护好后缀和,那么\(f\)数组的求解就是一个线性常系数齐次递推式。

暴力\(O(nk)\),矩乘\(O(k^3logn)\),这就\(90\)分了。

这个东西可以参考这里

因为特征多项式的系数是\(k\),所以多项式取模和多项式乘法可以暴力,这部分的复杂度就是\(O(k^2)\),加上快速幂的一个\(log\),所以这部分的复杂度就是\(O(k^2logk)\)。

暴力多项式乘法不用说,暴力多项式取模就是模拟长除法的过程,显然是一个\(O(k^2)\)的过程。

综上,本题的复杂度就是\(O(k^2logk)\)。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MOD 998244353
#define MAX 1010
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
int f[MAX][MAX],g[MAX][MAX],pw[MAX],p,np,n,K;
int M[MAX],pre[MAX<<1],A[MAX<<1],S[MAX<<1],B[MAX<<1],tmp[MAX<<1];
int Val(int a,int b){return 1ll*a*fpow(b,MOD-2)%MOD;}
void Mod(int *S,int len,int K)
{
for(int i=len;i>=K;--i)
{
int t=S[i];
for(int j=0;j<=K;++j)
S[i-j]=(S[i-j]+MOD-1ll*B[K-j]*t%MOD)%MOD;
}
}
int Solve(int K)
{
memset(f,0,sizeof(f));memset(g,0,sizeof(g));
memset(M,0,sizeof(M));memset(pre,0,sizeof(pre));
memset(S,0,sizeof(S));memset(A,0,sizeof(A));
memset(B,0,sizeof(B));memset(tmp,0,sizeof(tmp));
for(int i=1;i<=K+2;++i)f[0][i]=g[0][i]=1;
for(int i=1;i<=K;++i)
for(int j=K/i+1;j;--j)
{
for(int l=1;l<=i;++l)f[i][j]=(f[i][j]+1ll*g[l-1][j+1]*g[i-l][j]%MOD*pw[j-1]%MOD*np)%MOD;
g[i][j]=(g[i][j+1]+f[i][j])%MOD;
}
for(int i=0;i<=K;++i)M[i+1]=1ll*np*g[i][2]%MOD;
pre[0]=1;
for(int i=1;i<=K;++i)
for(int j=1;j<=i;++j)
pre[i]=(pre[i]+1ll*pre[i-j]*M[j])%MOD;
/*
for(int i=K+1;i<=n+1;++i)
for(int j=1;j<=K+1;++j)
pre[i]=(pre[i]+1ll*pre[i-j]*M[j])%MOD;
*/
if(n+1<=K)return 1ll*pre[n+1]*fpow(np,MOD-2)%MOD;
K+=1;
for(int i=0;i<K;++i)B[i]=(MOD-M[K-i])%MOD;B[K]=1;
A[1]=1;S[0]=1;int b=n+1;
while(b)
{
if(b&1)
{
for(int i=0;i<=K;++i)
for(int j=0;j<=K;++j)
tmp[i+j]=(tmp[i+j]+1ll*A[i]*S[j])%MOD;
for(int i=0;i<=K+K;++i)S[i]=tmp[i],tmp[i]=0;
Mod(S,K+K,K);
}
for(int i=0;i<=K;++i)
for(int j=0;j<=K;++j)
tmp[i+j]=(tmp[i+j]+1ll*A[i]*A[j])%MOD;
for(int i=0;i<=K+K;++i)A[i]=tmp[i],tmp[i]=0;
Mod(A,K+K,K);
b>>=1;
}
int ret=0;
for(int i=0;i<K;++i)ret=(ret+1ll*S[i]*pre[i])%MOD;
return 1ll*ret*fpow(np,MOD-2)%MOD;
}
int main()
{
n=read();K=read();p=read();p=1ll*p*fpow(read(),MOD-2)%MOD;np=(1+MOD-p)%MOD;
pw[0]=1;for(int i=1;i<=K;++i)pw[i]=1ll*pw[i-1]*p%MOD;
printf("%d\n",(Solve(K)-Solve(K-1)+MOD)%MOD);
return 0;
}

【BZOJ4944】[NOI2017]泳池(线性常系数齐次递推,动态规划)的更多相关文章

  1. 【Luogu4723】线性递推(常系数齐次线性递推)

    [Luogu4723]线性递推(常系数齐次线性递推) 题面 洛谷 题解 板子题QwQ,注意多项式除法那里每个多项式的系数,调了一天. #include<iostream> #include ...

  2. 【模板】BM + CH(线性递推式的求解,常系数齐次线性递推)

    这里所有的内容都将有关于一个线性递推: $f_{n} = \sum\limits_{i = 1}^{k} a_{i} * f_{n - i}$,其中$f_{0}, f_{1}, ... , f_{k ...

  3. 常系数齐次线性递推 & 拉格朗日插值

    常系数齐次线性递推 具体记在笔记本上了,以后可能补照片,这里稍微写一下,主要贴代码. 概述 形式: \[ h_n = a_1 h_{n-1}+a_2h_{n-2}+...+a_kh_{n-k} \] ...

  4. 【瞎讲】 Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18)

    [背诵瞎讲] Cayley-Hamilton 常系数齐次线性递推式第n项的快速计算 (m=1e5,n=1e18) 看CSP看到一题"线性递推式",不会做,去问了问zsy怎么做,他并 ...

  5. Re.常系数齐次递推

    前言 嗯   我之前的不知道多少天看这个的时候到底在干什么呢 为什么那么..  可能大佬们太强的缘故 最后仔细想想思路那么的emmm 不说了  要落泪了 唔唔唔 前置 多项式求逆 多项式除法/取模 常 ...

  6. 【BZOJ4161】Shlw loves matrixI (常系数齐次线性递推)

    [BZOJ4161]Shlw loves matrixI (常系数齐次线性递推) 题面 BZOJ 题解 \(k\)很小,可以直接暴力多项式乘法和取模. 然后就是常系数齐次线性递推那套理论了,戳这里 # ...

  7. BZOJ4161 常系数齐次线性递推

    问了数竞的毛毛搞了一番也没太明白,好在代码蛮好写先记下吧. #include<bits/stdc++.h> using namespace std; ,mod=1e9+; int n,k, ...

  8. LOJ 2304 「NOI2017」泳池——思路+DP+常系数线性齐次递推

    题目:https://loj.ac/problem/2304 看了各种题解…… \( dp[i][j] \) 表示有 i 列.第 j 行及以下默认合法,第 j+1 行至少有一个非法格子的概率,满足最大 ...

  9. BZOJ4944: [Noi2017]泳池

    BZOJ4944: [Noi2017]泳池 题目背景 久莲是个爱玩的女孩子. 暑假终于到了,久莲决定请她的朋友们来游泳,她打算先在她家的私人海滩外圈一块长方形的海域作为游泳场. 然而大海里有着各种各样 ...

随机推荐

  1. 前端开发CSS3——使用方式和选择器

    CSS是Cascading Style Sheets(层叠样式表)的简写,用于修饰文档的语言,可以修饰HTML.XML.SVN.每个语言都有每个语法的规则:CSS声明.CSS声明块.CSS选择器.CS ...

  2. 使用jqPrint.js调用浏览器打印界面,打印网页中的某一部分该部分含有ECharts图表

    1.准备好js文件(我用的是谷歌浏览器) 这个文件是为了防止你的jQuery版本过高而不适配的问题 这是调用浏览器打印的js插件 2.引入js文件 <script src="js/jq ...

  3. Struts2 在Action中操作数据

    Servlet存储数据的方式 在Servlet中,使用ServletContext对象来存储整个WebApp的数据,ServletContext中直接存储整个WebApp的公共数据,可使用set|ge ...

  4. commons-dbutils【不推荐】

    Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装. 一般项目开发过程中,要么选择 ORM框架,要么自己编写DBUtils类+数据库连接池就足够了.

  5. 8、RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较

    RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较 RabbitMQ中,除了Simple Queue和Work Queue之外的所有生产者提交的消息都由Exc ...

  6. JS高阶---作用域与作用域链

    大纲: 主体: (1)概论 (2)层级 执行上下文层级为n+1原则 作用域层级也是n+1原则 验证: (3)函数作用域作用 隔离变量,不同作用域下,相同变量名不会有冲突 (4) .

  7. python实验脚本

    day1 1.  任性猜数字 需求 : 猜数字, 猜3次.如果对了 就直接退出. 如果3次都错了 ,就询问 要不要继续. 实现点: 使用 whie 循环. count 进行计数.如果count > ...

  8. 201871010102-常龙龙《面向对象程序设计(java)》第十七周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  9. mac os下切换pip3国内源并安装requests库

    在使用Python的时候,经常会用到pip来安装模块,但是默认的下载源实在是特别慢,经常install的时候还会因为速度的原因直接报错,因此我们可以选择将下载源更改为国内的,这样就可以提高我们的下载速 ...

  10. python27期尚哥讲并发编程:

    python27day23并发编程----------------------------------------------------------------------------------- ...