Description

Link.

这道题 的加强版。

Solution

题解里面大多数都是概率 DP,或者是期望 DP 然后是逆推。甚至不给 DP 的转移式。机房 yyds Reanap 发了一篇逆推的题解,那我就来补一篇正推的期望 DP 的填表法做法。

首先这道题看上去好像可以状压的样子,我们可以设 \(f_{i,S}\) 表示当前打了 \(i\) 次,敌方的情况是 \(S\) 的期望。

不过仔细想一下发现我们只需要知道各种血量的奴隶主有多少即可。

于是我们重新设计 DP 的状态:\(f_{s,i,j,k}\) 表示目前打了 \(s\) 次,敌方分别有 \(i\)、\(j\)、\(k\) 个 1hp、2hp、3hp 的奴隶主。

首先我们令 \(T=[i+j+k<K]\)

那么我们的方程就是:

\[f_{s,i,j,k}=\begin{cases}
f_{s-1,i-1,j,k}+\frac{i}{i+j+k+1},M=1\land i\neq0 \\
f_{s-1,i-1,j,k}+\frac{i}{i+j+k+1},M=2\land i\neq0 \\
f_{s-1,i+1,j-1+T,k}+\frac{j}{i+j+k+1},M=2\land j\neq0 \\
f_{s-1,i-1,j,k}+\frac{i}{i+j+k+1},M=3\land i\neq0 \\
f_{s-1,i+1,j-1,k+T}+\frac{j}{i+j+k+1},M=3\land j\neq0 \\
f_{s-1,i,j+1,k-1+T}+\frac{k}{i+j+k+1},M=3\land k\neq0
\end{cases}
\]

这个方程挺好理解的,基本就等于照题意模拟。

然后我们发现转移式中的系数部分和 \(f\) 数组没有关系,所以我们可以用矩阵来加速这个东西。

数一数状态数,直接加速直接 T 飞。

有一个矩阵加速常用的 trick,预处理矩阵 2 的幂。

然后取模卡卡常即可。

(代码不保证稳定能过)

#include <cstdio>
#define mod ( 998244353 ) using namespace std;
typedef long long LL; char buf[1 << 21], *p1 = buf, *p2 = buf;
#define getchar( ) ( p1 == p2 && ( p2 = ( p1 = buf ) + fread( buf, 1, 1 << 21, stdin ), p1 == p2 ) ? EOF : *p1 ++ ) template<typename _T>
void read( _T &x )
{
x = 0;
char c = getchar( );
_T f = 1;
while( c < '0' || c > '9' )
{
if( c == '-' ) f = -1;
c = getchar( );
}
while( c >= '0' && c <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ( c ^ '0' ), c = getchar( );
x *= f;
} template<typename _T, typename... Args>
void read( _T &t, Args&... args ) { read( t ), read( args... ); } template<typename _T>
void write( _T x )
{
if( x < 0 ) putchar( '-' ), x = -x;
if( x > 9 ) write( x / 10 );
putchar( x % 10 + '0' );
} template<typename _T>
void Add( _T &x, _T y )
{
if( y >= mod ) y %= mod;
x += y;
if( x >= mod ) x -= mod;
} template<typename _T>
_T square( _T x ) { return x * x; } const int Maxn = 10 + 5, Maxk = 170 + 5;
int T, M, K, S, Unite[Maxn][Maxn][Maxn];
LL tmp[Maxk], Ans[Maxk], Inv[Maxn];
struct Matrix
{
LL mat[Maxk][Maxk]; friend Matrix operator * ( const Matrix &one, const Matrix &another )
{
Matrix res;
for( int i = 0; i <= S + 1; ++ i )
{
for( int j = 0; j <= S + 1; ++ j )
{
res.mat[i][j] = 0;
for( int k = 0; k <= S + 1; ++ k ) Add( res.mat[i][j], one.mat[i][k] * another.mat[k][j] );
}
}
return res;
}
} dp[Maxk]; template<typename _T>
_T qkpow( _T base, _T times )
{
_T res = 1;
while( times )
{
if( times & 1 ) res = ( LL )res * base % mod;
base = ( LL )base * base % mod;
times >>= 1;
}
return res;
} void progressInversions( ) { for( int i = 0; i <= 10; ++ i ) Inv[i] = qkpow( i, mod - 2 ); }
signed main( )
{
progressInversions( );
read( T, M, K );
for( int i = 0; i <= K; ++ i )
{
int UpI;
if( M > 1 ) UpI = K - i;
else UpI = 0;
for( int j = 0; j <= UpI; ++ j )
{
int UpJ;
if( M > 2 ) UpJ = K - i - j;
else UpJ = 0;
for( int k = 0; k <= UpJ; ++ k ) Unite[i][j][k] = ++ S;
}
}
for( int i = 0; i <= K; ++ i )
{
int UpI;
if( M > 1 ) UpI = K - i;
else UpI = 0;
for( int j = 0; j <= UpI; ++ j )
{
int UpJ;
if( M > 2 ) UpJ = K - i - j;
else UpJ = 0;
for( int k = 0; k <= UpJ; ++ k )
{
int Add;
if( i + j + k < K ) Add = 1;
else Add = 0;
if( M == 1 && i ) dp[0].mat[Unite[i][j][k]][Unite[i - 1][j][k]] = ( LL )i * Inv[i + j + k + 1] % mod;
else if( M == 2 )
{
if( i ) dp[0].mat[Unite[i][j][k]][Unite[i - 1][j][k]] = ( LL )i * Inv[i + j + k + 1] % mod;
if( j ) dp[0].mat[Unite[i][j][k]][Unite[i + 1][j - 1 + Add][k]] = ( LL )j * Inv[i + j + k + 1] % mod;
}
else if( M == 3 )
{
if( i ) dp[0].mat[Unite[i][j][k]][Unite[i - 1][j][k]] = ( LL )i * Inv[i + j + k + 1] % mod;
if( j ) dp[0].mat[Unite[i][j][k]][Unite[i + 1][j - 1][k + Add]] = ( LL )j * Inv[i + j + k + 1] % mod;
if( k ) dp[0].mat[Unite[i][j][k]][Unite[i][j + 1][k - 1 + Add]] = ( LL )k * Inv[i + j + k + 1] % mod;
}
dp[0].mat[Unite[i][j][k]][Unite[i][j][k]] = dp[0].mat[Unite[i][j][k]][S + 1] = Inv[i + j + k + 1];
}
}
}
dp[0].mat[S + 1][S + 1] = 1;
for( int i = 1; i <= 60; ++ i ) dp[i] = square( dp[i - 1] );
while( T -- > 0 )
{
LL N;
read( N );
for( int i = 0; i <= S + 1; ++ i ) Ans[i] = 0;
if( M == 1 ) Ans[Unite[1][0][0]] = 1;
else if( M == 2 ) Ans[Unite[0][1][0]] = 1;
else Ans[Unite[0][0][1]] = 1;
for( int i = 0; i <= 60; ++ i )
{
if( ( N >> i ) & 1 )
{
for( int j = 0; j <= S + 1; ++ j )
{
tmp[j] = 0;
for( int k = 0; k <= S + 1; ++ k ) Add( tmp[j], Ans[k] * dp[i].mat[k][j] );
}
for( int j = 0; j <= S + 1; ++ j ) Ans[j] = tmp[j];
}
}
write( Ans[S + 1] ), putchar( '\n' );
}
return 0;
}

Solution -「洛谷 P4007」小 Y 和恐怖的奴隶主的更多相关文章

  1. loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主

    #2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较   题目描述 "A fight? Co ...

  2. 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法

    题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...

  3. LibreOJ #2325. 「清华集训 2017」小Y和恐怖的奴隶主(矩阵快速幂优化DP)

    哇这题剧毒,卡了好久常数才过T_T 设$f(i,s)$为到第$i$轮攻击,怪物状态为$s$时对boss的期望伤害,$sum$为状态$s$所表示的怪物个数,得到朴素的DP方程$f(i,s)=\sum \ ...

  4. LOJ2325. 「清华集训 2017」小 Y 和恐怖的奴隶主【矩阵快速幂优化DP】【倍增优化】

    LINK 思路 首先是考虑怎么设计dp的状态 发现奴隶主的顺序没有影响,只有生命和个数有影响,所以就可以把每个生命值的奴隶主有多少压缩成状态就可以了 然后发现无论是什么时候一个状态到另一个状态的转移都 ...

  5. LOJ2325「清华集训 2017」小Y和恐怖的奴隶主

    题目链接 首先dp很显然,\(f(i,s)\)表示到了第i轮,各种血量人数的情况为s今后的期望攻击boss次数.那么有\(f(i,s)=\frac{1}{num+1}*\sum_{s->s'}( ...

  6. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  7. Note/Solution -「洛谷 P5158」「模板」多项式快速插值

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个点 \((x_i,y_i)\),求一个不超过 \(n-1\) 次的多项式 \(f(x)\),使得 \(f(x ...

  8. Solution -「洛谷 P4719」「模板」"动态 DP" & 动态树分治

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个结点的带权树,\(m\) 次单点点权修改,求出每次修改后的带权最大独立集.   \(n,m\le10^5 ...

  9. Solution -「洛谷 P4198」楼房重建

    \(\mathcal{Description}\)   Link.   给定点集 \(\{P_n\}\),\(P_i=(i,h_i)\),\(m\) 次修改,每次修改某个 \(h_i\),在每次修改后 ...

  10. Solution -「洛谷 P6577」「模板」二分图最大权完美匹配

    \(\mathcal{Description}\)   Link.   给定二分图 \(G=(V=X\cup Y,E)\),\(|X|=|Y|=n\),边 \((u,v)\in E\) 有权 \(w( ...

随机推荐

  1. html+css简单易懂的轮播图实现

    实现轮播图感觉好复杂啊,这个比较简单的实现了 但是还是没有怎么理解代码,只能先发出来慢慢学习学习了 话不多说,直接上代码 <!DOCTYPE html> <html lang=&qu ...

  2. ARC143

    ARC143 考试情况:一眼订正,鉴定为做出前三题. A - Three Integers 以前做过 \(n\) 个数的版本,当时还被某人嘲讽说"堆,贪心,这都做不出来?". \( ...

  3. DHCP配置;DHCP Relay配置

    目录 DHCP 配置 实验拓扑 实验需求 实验步骤 1. 基于全局地址池的DHCP服务器给客户端分配IP地址 DHCP server 上配置如下 2. 在PC1上设置为DHCP自动获取方式,ipcon ...

  4. Hyperledger Fabric系统链码介绍

    在Hyperledger Fabric中,LSCC(Lifecycle System Chaincode).CSCC(Chaincode System Chaincode).QSCC(Query Sy ...

  5. 生成式预训练Transformer在机器翻译中的应用与挑战

    目录 1. 引言 2. 技术原理及概念 3. 实现步骤与流程 4. 应用示例与代码实现讲解 5. 优化与改进 6. 结论与展望 机器翻译是人工智能领域的重要应用之一,而生成式预训练Transforme ...

  6. 数据库varchar和tinyint和int和java实体属性的对应关系的学习

    大家好,最近做项目碰到群里小伙伴的对于项目中用到的这几个类型,自己的java实体类属性该用什么类型干到困惑,于是乎,我决定为大家解密! 相信我,绝对干货,看完了,工资+200~哈哈哈,扯远了,闲话不对 ...

  7. 【Promptulate】一个强大的LLM Prompt Layer框架

    本文节选自笔者博客: https://www.blog.zeeland.cn/archives/promptulate666 前言 在构建了[prompt-me]一个专为 Prompt Enginee ...

  8. PostgreSQL 12 文档: 部分 I. 教程

    部分 I. 教程 欢迎来到PostgreSQL教程.下面的几章将为那些新接触PostgreSQL.关系数据库概念和 SQL 语言的读者给出一个简单介绍.我们只假定读者拥有关于如何使用计算机的一般知识. ...

  9. 使用部分写时复制提升Lakehouse的 ACID Upserts性能

    使用部分写时复制提升Lakehouse的 ACID Upserts性能 译自:Fast Copy-On-Write within Apache Parquet for Data Lakehouse A ...

  10. maven报错:不再支持源选项 5。请使用 6 或更高版本

    问题描述 在执行命令 mvn compile 发生错误 D:\Github_NOTES\JavaWeb_Learning\02Java\JavaWeb\Code\Maven1>mvn clean ...