C221027B
B
- 抽 \(n\) 次卡, 连续 \(i\) 次没有抽中时, 第 \(i+1\) 次抽中的概率是 \(p_i\), 规定\(p_k=1\), 求期望抽中次数.
- 标签:矩阵加速递推, 动态规划.
- 暴力: 记 \(f[i][j]\) 表示已经抽了 \(i\) 次, 目前连续 \(j\) 次不中的期望抽中次数,有转移:
f[i][0]=\sum_{j=0}^{k}f[i-1][j] \times p[j]
\]
时间复杂度 \(O(NK)\).
优化:矩阵加速递推
- \[\begin{bmatrix}
p_0 & p_1 & p_2 & \cdots & p_k & 0 \\
1-p_0 & 0 & 0 & \cdots & 0 & 0 \\
0 & 1-p_1& 0 &\cdots & 0 & 0 \\
0 & 0 & 1-p_2&\cdots & 0 & 0 \\
\vdots & \vdots & \vdots & \ddots & \vdots & \vdots\\
0 & 0 & \cdots & 1-p_{k-1} & 0 & 0\\
0 & 0 & \cdots & 0 & 0 & 0 \\
p_0 & p_1 & p_2 & \cdots & p_k & 1 \\
\end{bmatrix}
\times
\begin{bmatrix}
f_{0} \\
f_{1} \\
f_{2} \\
\vdots \\
f_{k} \\
res \\
\end{bmatrix}
\] 记矩阵为 \(A\)(一个 边长为 \(k+2\) 的方阵), 列向量为 \(F_0\)(其中 \(f_i=1,f_{1 \sim k}=0\))
先用矩阵快速幂求出 \(A^n \times F_0\), 答案就是 \(res\)
时间复杂度:本来是\(O(K^3 \times log_2^N)\), 但有一个小优化是每次
y&1=1的时候不要另开一个单位矩阵存答案, 直接累计到那个行向量里面,这样时间复杂度会有一个 \(\frac{1}{2}\) 的常数, 会快一倍
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
#define G(i,r,l) for(int i(r);i>=l;--i)
using namespace std;
using ll = long long;
const int mod=998244353;
int a[205],b[205],p[205];
int n,k;
struct matrix{
int a[205][205];
void init(int val=0){
memset(a,0,sizeof(a));
F(i,0,k+1) a[i][i]=val;
}
}v;
matrix operator $ (matrix A,matrix B){
matrix C; C.init(0);
F(i,0,k+1) F(j,0,k+1) F(z,0,k+1) C.a[i][z]=(C.a[i][z]+1ll$A.a[i][j]$B.a[j][z]%mod)%mod;
return C;
}
void ksm(matrix A,int b){
int f[205],g[205];
memset(f,0,sizeof(f));
f[0]=1;
while(b){
if(b&1){
memset(g,0,sizeof(g));
F(i,0,k+1) F(j,0,k+1) g[i]=(g[i]+1ll$A.a[i][j]$f[j])%mod;//优化在这里,单次变成K^2
memcpy(f,g,sizeof(f));
}
A=A$A;
b>>=1;
}
cout<<(f[k+1]%mod+mod)%mod;
}
int quickmod(int x,int y){
int res=1;
while(y){
if(y&1) res=1ll$res$x%mod;
x=1ll$x$x%mod;
y>>=1;
} return res;
}
signed main(){
freopen("card.in","r",stdin);
freopen("card.out","w",stdout);
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n>>k;
F(i,0,k-1){
cin>>a[i]>>b[i];
p[i]=1ll$a[i]$quickmod(b[i],mod-2)%mod;
} p[k]=1;
v.init(0);
F(i,0,k) v.a[0][i]=v.a[k+1][i]=p[i];
F(i,1,k) v.a[i][i-1]=1-p[i-1];
v.a[k+1][k+1]=1;
ksm(v,n);
return 0;
}
随机推荐
- JavaScript设计模式样例十五 —— 状态模式
状态模式(State Pattern) 定义:创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象.目的:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类 ...
- C#读写图片文件到Access数据库中
今天学习了把图片文件读写到数据库中,我是用的Access数据库,SQL还没去测试,不过都差不多 数据库表的样式 练习嘛就随便弄了下,说明下图片转成的字符串要用备注类型才可以哦 如果用的Sql数据库的话 ...
- Odoo13开发环境搭建
准备:windows10 64位系统.Python3.6.8.Pycharm2019.2.Postgresql-12.0-1.Odoo13 其它:nodejs.rtlcss.wkhtmltopdf 安 ...
- 主观与客观,破除DDD凭经验魔咒
本文书接上回<学习真DDD的最佳路径>,关注公众号(老肖想当外语大佬)获取信息: 最新文章更新: DDD框架源码(.NET.Java双平台): 加群畅聊,建模分析.技术实现交流: 视频和直 ...
- docker高级篇:实战-自己开发的微服务怎么在docker上面运行?
通过前面的一系列学习,我们已经知道怎么制作dockerfile了.那么,本篇文章,咱们就把自己写的spring boot的demo项目,部署在docker上面. 案例目标: 我们自己开发的微服务怎么在 ...
- python pyqt6 设定logo图标
如果是Window self.setWindowIcon(QIcon(get_icon('logo.png'))) 如果是Dialog self.login_dialog.setWindowIcon( ...
- attention, transformers
这啥呀,慢慢啃 Attention 最初来源于 NLP 机器翻译的 Sequence to Sequence 模型,早先的encoder-decoder结构随着句子长度增加翻译性能会下降,因为模型记不 ...
- request和response请求包中的各项解释
Request Response
- Go 语言中值接收者和指针接收者方法调用的自动转换规则详解
在 Go 语言中,方法的调用规则对于值接收者和指针接收者有一些特别的行为,这使得代码变得更加简洁和易用.我们来详细解释一下"方法值调用规则"和"方法表达式调用规则&quo ...
- usb请求块以及提交方式
URB结构体 struct urb { /* private: usb core and host controller only fields in the urb */ struct kref k ...