「NOI2017」泳池
DP式子比后面的东西难推多了
题意
给定一个长度为$ n$高为$ \infty$的矩形
每个点有$ 1-P$的概率不可被选择
求最大的和底边重合的不包含不可选点的矩形的面积为$ K$的概率
$ n \leq 10^9 k \leq 10^3$
题解
K可以出到50000的
首先考虑DP
面积恰好为$ K$的概率可以差分为不高于$ K$的概率减去不高于$ K-1$的概率
设$ f[i][j]$表示长度为$ i$的矩形,从底边起$ j$行都可选,最大面积不大于$ K$的概率
边界为$ f[0][j]=1,f[i][j]=0 当且仅当i*j>k$
考虑转移,要么第$ j+1$行也都可选,要么第$ j+1$行有不可选的位置
对于第二种情况我们枚举从左到右第一个不可选的位置
有转移方程式
$$f[i][j]=f[i][j+1]*P^i+\sum_{k=1}^iP^{k-1}(1-P)f[k-1][j+1]·f[i-k][j]$$
我们要求的是$ f[n][0]$
由于$ i*j \leq K$因此复杂度大致是$ n·k \log k$的
可以得$ 70$分
容易发现当$ n$远大于$ k$的时候,每连续$ k$列必然有一列最低端有不可选点
令$ F[i]$表示当$ i>k$时,长度为$ i$的矩形的答案
枚举从右往左第一个不可选点,有转移方程式
$$ F[i]=f[i-k]*(1-P)*f[k-1][1]*P^{k-1}$$
这是一个线性递推的标准形式,可以用特征多项式优化到$ O(k^2 \log n)$甚至$ O(k \log k \log n)$
如果采用后一种的话复杂度的瓶颈在于前面的$ O(k^2)DP$,这部分可以用分治$ NTT$优化
然而我并没有写
代码
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define p 998244353
#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');}
namespace poly{
vector<int>R;
int ksm(int x,int y=p-){
int ans=;
for(rt i=y;i;i>>=,x=1ll*x*x%p)if(i&)ans=1ll*ans*x%p;
return ans;
}
void NTT(int n,vector<int>&A,int fla){
A.resize(n);
for(rt i=;i<n;i++)if(i>R[i])swap(A[i],A[R[i]]);
for(rt i=;i<n;i<<=){
int w=ksm(,(p-)//i);
for(rt j=;j<n;j+=i<<){
int K=;
for(rt k=;k<i;k++,K=1ll*K*w%p){
int x=A[j+k],y=1ll*K*A[i+j+k]%p;
A[j+k]=(x+y)%p,A[i+j+k]=(x-y)%p;
}
}
}
if(fla==-){
reverse(A.begin()+,A.end());
int invn=ksm(n);
for(rt i=;i<n;i++)A[i]=1ll*A[i]*invn%p;
}
}
vector<int>Mul(vector<int>x,vector<int>y){
int lim=,sz=x.size()+y.size()-;
while(lim<=sz)lim<<=;R.resize(lim);
for(rt i=;i<lim;i++)R[i]=(R[i>>]>>)|(i&)*(lim>>);
NTT(lim,x,);NTT(lim,y,);
for(rt i=;i<lim;i++)x[i]=1ll*x[i]*y[i]%p;
NTT(lim,x,-);x.resize(sz);
return x;
}
vector<int>sqr(vector<int>x){
int lim=,sz=x.size()*-;
while(lim<=sz)lim<<=;R.resize(lim);
for(rt i=;i<lim;i++)R[i]=(R[i>>]>>)|(i&)*(lim>>);
NTT(lim,x,);for(rt i=;i<lim;i++)x[i]=1ll*x[i]*x[i]%p;
NTT(lim,x,-);x.resize(sz);
return x;
}
vector<int>Inv(vector<int>A,int n=-){
if(n==-)n=A.size();
if(n==)return vector<int>(,ksm(A[]));
vector<int>b=Inv(A,(n+)/);
int lim=;while(lim<=n+n)lim<<=;R.resize(lim);
for(rt i=;i<lim;i++)R[i]=(R[i>>]>>)|(i&)*(lim>>);
A.resize(n);NTT(lim,A,);NTT(lim,b,);
for(rt i=;i<lim;i++)A[i]=1ll*b[i]*(2ll-1ll*A[i]*b[i]%p)%p;
NTT(lim,A,-);A.resize(n);
return A;
}
vector<int>Div(vector<int>A,vector<int>B){
int n=A.size(),m=B.size();
reverse(A.begin(),A.end());
reverse(B.begin(),B.end());
A.resize(n-m+),B.resize(n-m+);
int lim=;while(lim<=*(n-m+))lim<<=;R.resize(lim);
for(rt i=;i<lim;i++)R[i]=(R[i>>]>>)|(i&)*(lim>>);
vector<int>ans=Mul(A,Inv(B));ans.resize(n-m+);
reverse(ans.begin(),ans.end());
return ans;
}
vector<int>add(vector<int>A,vector<int>B){
int len=max(A.size(),B.size());A.resize(len+);
for(rt i=;i<=len;i++)(A[i]+=B[i])%=p;
return A;
}
vector<int>sub(vector<int>A,vector<int>B){
int len=max(A.size(),B.size());A.resize(len+);
for(rt i=;i<=len;i++)(A[i]-=B[i])%=p;
return A;
}
vector<int>Mod(vector<int>x,vector<int>y){
if(x.size()<=y.size())return x;
vector<int>ans=Div(x,y);
ans=sub(x,Mul(y,ans));
while(!ans[ans.size()-])ans.pop_back();
if(ans.size()>y.size())ans.resize(y.size());
return ans;
}
}
using namespace poly;
int a[];
vector<int>fmo;
vector<int>ksm(vector<int>x,int y){
if(y==)return x;
vector<int>ans=Mod(sqr(ksm(x,y>>)),fmo);
if(y&){
ans.push_back();
for(rt i=ans.size()-;i>=;i--)ans[i+]=ans[i],ans[i]=;
}
return ans;
}
using namespace poly;
int k,m,n,x,y,z,cnt,ans,K,P;
int f[][],mi[];
//f[i][j]长度为i合法高度最低至少为j的合法概率
void calc(int n,int K,int fla){
memset(f,,sizeof(f));
for(rt i=;i<=K+;i++)f[][i]=;
for(rt i=;i<=K+;i++)
for(rt j=K/i;j>=;j--){
f[i][j]=1ll*f[i][j+]*mi[i]%p;
for(rt k=;k<=i;k++)(f[i][j]+=1ll*f[k-][j+]*mi[k-]%p*(+p-P)%p*f[i-k][j]%p)%=p;
}
fmo.resize(K+);
for(rt j=;j<=K+;j++)fmo[K+-j]=-1ll*mi[j-]*f[j-][]%p*(p+-P)%p;
fmo[K+]=;int ret=;
if(n<=K+)ret=f[n][];else {
vector<int>x;x.push_back();x.push_back();
x=ksm(x,n);
for(rt i=;i<=K+;i++)(ret+=1ll*f[i][]*x[i]%p)%=p;
}
(ans+=ret*fla)%=p;
}
int main(){
// file("pool");
n=read();K=read();x=read();y=read();P=1ll*x*ksm(y)%p;
mi[]=;for(rt i=;i<=K+;i++)mi[i]=1ll*mi[i-]*P%p;
calc(n,K,);calc(n,K-,-);cout<<(ans+p)%p;
return ;
}
「NOI2017」泳池的更多相关文章
- LOJ#2304. 「NOI2017」泳池
$n \leq 1e9$底边长的泳池,好懒啊泥萌自己看题吧,$k \leq 1000$.答案对998244353取膜. 现在令$P$为安全,$Q$为危险的概率.刚好$K$是极其不好算的,于是来算$\l ...
- LOJ 2304 「NOI2017」泳池——思路+DP+常系数线性齐次递推
题目:https://loj.ac/problem/2304 看了各种题解…… \( dp[i][j] \) 表示有 i 列.第 j 行及以下默认合法,第 j+1 行至少有一个非法格子的概率,满足最大 ...
- LOJ_2305_「NOI2017」游戏 _2-sat
LOJ_2305_「NOI2017」游戏 _2-sat 题意: 给你一个长度为n的字符串S,其中第i个字符为a表示第i个地图只能用B,C两种赛车,为b表示第i个地图只能用A,C两种赛车,为c表示第i个 ...
- 「NOI2017」游戏
「NOI2017」游戏 题目描述 小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 \(A\).\(B\).\ ...
- loj #2305. 「NOI2017」游戏
#2305. 「NOI2017」游戏 题目描述 小 L 计划进行 nnn 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 AAA.BBB. ...
- LOJ2305 「NOI2017」游戏
「NOI2017」游戏 题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行$n$场 ...
- LOJ2303 「NOI2017」蚯蚓排队
「NOI2017」蚯蚓排队 题目描述 蚯蚓幼儿园有$n$只蚯蚓.幼儿园园长神刀手为了管理方便,时常让这些蚯蚓们列队表演. 所有蚯蚓用从$1$到$n$的连续正整数编号.每只蚯蚓的长度可以用一个正整数表示 ...
- LibreOJ2302 - 「NOI2017」整数
Portal Description 有一个整数\(x=0\),对其进行\(n(n\leq10^6)\)次操作: 给出\(a(|a|\leq10^9),b(b\leq30n)\),将\(x\)加上\( ...
- 「NOI2017」蔬菜 解题报告
「NOI2017」蔬菜 首先考虑流 可以从 \(s\) 流入表示得到蔬菜,流出到 \(t\) 表示卖出蔬菜,给每个蔬菜拆点,并给它它每天应得的蔬菜. 但是我们没办法直接给,注意到如果把变质看成得到并可 ...
随机推荐
- MySQL之视图、触发器、事务、存储过程、函数
一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的 ...
- 文本分类实战(四)—— Bi-LSTM模型
1 大纲概述 文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类.总共有以下系列: word2vec预训练词向量 te ...
- 转://ORA-00603,ORA-27501,ORA-27300,ORA-27301,ORA-27302故障案例一则
背景介绍: 这是一套windows的rac系统.数据库后台日志报ORA-00474:SMON process terminated with error.接着报ORA-00603,ORA-27501, ...
- ORACLE 常见等待事件
一. 等待事件的相关知识 1.1 等待事件主要可以分为两类,即空闲(IDLE)等待事件和非空闲(NON-IDLE)等待事件.1). 空闲等待事件指ORACLE正等待某种工作,在诊断和优化数据库的时候, ...
- redis 初步认识三(设置登录密码)
1.cmd 2.cd C:\Program Files\Redis 3.redis-cli.exe -h 127.0.0.1 -a 123456
- 《通过C#学Proto.Actor模型》之 HelloWorld
在微服务中,数据最终一致性的一个解决方案是通过有状态的Actor模型来达到,那什么是Actor模型呢? Actor是并行的计算模型,包含状态,行为,并且包含一个邮箱,来异步处理消息. 关于Actor的 ...
- Web Storage和cookie
Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生; Web Storage的概念和cookie相似,区别是它是为了更大容 ...
- 云计算openstack共享组件(3)——消息队列rabbitmq
队列(MQ)概念: MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链 ...
- gorose使用示例
package main import ( "fmt" "github.com/gohouse/gorose" //import Gorose _ " ...
- BZOJ3328 PYXFIB 单位根反演
题意:求 \[ \sum_{i=0}^n[k|i]\binom{n}{i}Fib(i) \] 斐波那契数列有简单的矩阵上的通项公式\(Fib(n)=A^n_{1,1}\).代入得 \[ =\sum_{ ...