B

  • 抽 \(n\) 次卡, 连续 \(i\) 次没有抽中时, 第 \(i+1\) 次抽中的概率是 \(p_i\), 规定\(p_k=1\), 求期望抽中次数.
  • 标签:矩阵加速递推, 动态规划.
  • 暴力: 记 \(f[i][j]\) 表示已经抽了 \(i\) 次, 目前连续 \(j\) 次不中的期望抽中次数,有转移:
\[f[i][j]=f[i-1][j-1] \times (1-p[j-1]) \\
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;
}

随机推荐

  1. [考试记录] 2024.7.15 csp-s模拟赛4

    2024.7.15 csp-s模拟赛4 T1 传送带 题面翻译 有一个长度为 \(n\) 的一维网格.网格的第 \(i\) 个单元格包含字符 \(s_i\) ,是"<"或&q ...

  2. 18-canvas绘制饼状图

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  3. LVM逻辑卷创建

    创建步骤 1.创建分区 2.创建PV 3.创建VG 4.创建LV 5.格式化及挂载 创建分区 使用分区工具(如fdisk等)创建LVM分区. 创建PV $ pvcreate /dev/sdb5 #将每 ...

  4. Windows C 盘瘦身

    修改 Window 服务器虚拟内存位置 | 博客园 怎么更改电脑默认储存位置呢?| CSDN Win11 磁盘清理怎么没有了?Win11 磁盘清理在哪打开?| 搜狐网 快速清理 Windows 大文件 ...

  5. 《花100块做个摸鱼小网站! 》第五篇—通过xxl-job定时获取热搜数据

    ️基础链接导航️ 服务器 → ️ 阿里云活动地址 看样例 → 摸鱼小网站地址 学代码 → 源码库地址 一.前言 我们已经成功实现了一个完整的热搜组件,从后端到前端,构建了这个小网站的核心功能.接下来, ...

  6. Kali初次使用,如何获得root权限?【转】

    最新的kali 系统,安装的时候会创建一个新用户,不是root的,然后安装软件的时候会要求root权限,要启用root账号可以按下面这个写的 方法1已经确认可以.方法2没尝试,自己试试吧. 1.确定用 ...

  7. elementUI实现月、季度、年 时间选择框

    elementUI实现月.季度.年 时间选择框 一.通过 el-date-picker 组件来实现月.年的选择 代码如下: <el-date-picker v-if="dateType ...

  8. Asp.net core 学习笔记之 authen + autho + oidc + oauth + spa 第九篇 (external login)

    External login 就是指通过 Google, Microsoft, Facebook account 做登入. https://docs.microsoft.com/en-us/aspne ...

  9. Servlet——Request请求转发

    Request请求转发       特点:     

  10. ArgoWorkflow教程(五)---Workflow 的多种触发模式:手动、定时任务与事件触发

    上一篇我们分析了argo-workflow 中的 archive,包括 流水线GC.流水线归档.日志归档等功能.本篇主要分析 Workflow 中的几种触发方式,包括手动触发.定时触发.Event 事 ...