LINK


思路

首先是考虑怎么设计dp的状态

发现奴隶主的顺序没有影响,只有生命和个数有影响,所以就可以把每个生命值的奴隶主有多少压缩成状态就可以了

然后发现无论是什么时候一个状态到另一个状态的转移都是固定的方式

所以可以预处理转移矩阵用矩阵快速幂进行优化

但是如果在计算的时候暴力\(状态^3\)进行转移会TLE

但是注意到在这个时候有用的状态其实只有一个向量

所以就预处理倍增然后用向量乘矩阵来优化到单次\(logn状态^2\)就可以了

有点卡常


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) x = (x<<1) + (x<<3) + c -'0', c = getchar();
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 170;
const int Mod = 998244353;
ll n, m, K, cnt = 0;
int inv[10];
int id[9][9][9];
struct Matrix{
int t[N][N];
Matrix() { memset(t, 0, sizeof(t));}
}trans, g[61];
inline int add(int a, int b) { return ((a += b) > Mod) ? (a - Mod) : a; }
inline int mul(int a, int b) { return 1ll * a * b % Mod; }
Matrix operator * (const Matrix a, const Matrix b) {
Matrix c;
fu(k, 0, cnt)
fu(i, 0, cnt) if (a.t[i][k])
fu(j, 0, cnt)
c.t[i][j] = add(c.t[i][j], mul(a.t[i][k], b.t[k][j]));
return c;
}
inline Matrix mul_matrix(Matrix a, Matrix b) {
Matrix c;
fu(k, 0, cnt) if(a.t[0][k])
fu(j, 0, cnt)
c.t[0][j] = add(c.t[0][j], mul(a.t[0][k], b.t[k][j]));
return c;
}
inline int fast_pow(int a, int b) {
int ans = 1;
while (b) {
if (b & 1) ans = mul(ans, a);
b >>= 1;
a = mul(a, a);
}
return ans;
}
inline int get_add_id(int i, int j, int k) {
if (i + j + k == K) return id[i][j][k];
if (m == 1) return id[i + 1][j][k];
if (m == 2) return id[i][j + 1][k];
if (m == 3) return id[i][j][k + 1];
}
void init() {
fu(i, 1, K + 1)inv[i] = fast_pow(i, Mod - 2);
int upj, upk, ID, inv_sum;
fu(i, 0, K) {
upj = (m == 1)? 0 : K - i;
fu(j, 0, upj) {
upk = (m == 2)? 0 : K - i - j;
fu(k, 0, upk) id[i][j][k] = ++cnt;
}
}
++cnt;
trans.t[cnt][cnt] = 1;
fu(i, 0, K) {
upj = (m == 1)? 0 : K - i;
fu(j, 0, upj) {
upk = (m == 2)? 0 : K - i - j;
fu(k, 0, upk) {
ID = id[i][j][k], inv_sum = inv[i + j + k + 1];
if (i) trans.t[ID][id[i - 1][j][k]] = mul(inv_sum, i);
if (j) trans.t[ID][get_add_id(i + 1, j - 1, k)] = mul(inv_sum, j);
if (k) trans.t[ID][get_add_id(i, j + 1, k - 1)] = mul(inv_sum, k);
trans.t[ID][ID] = trans.t[ID][cnt] = inv_sum;
}
}
}
g[0] = trans;
fu(i, 1, 60) g[i] = g[i - 1] * g[i - 1];
}
int main() {
#ifdef dream_maker
freopen("input.txt","r",stdin);
#endif
int T;Read(T);
Read(m); Read(K);
init();
int pre = get_add_id(0, 0, 0);
while (T--) {
Read(n);
Matrix ans;
ans.t[0][pre] = 1;
fu(i, 0, 60)
if ((n >> i) & 1) ans = mul_matrix(ans, g[i]);
printf("%d\n", ans.t[0][cnt]);
}
return 0;
}

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

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

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

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

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

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

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

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

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

  5. Loj #2324. 「清华集训 2017」小 Y 和二叉树

    Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...

  6. [LOJ#2324]「清华集训 2017」小Y和二叉树

    [LOJ#2324]「清华集训 2017」小Y和二叉树 试题描述 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙 ...

  7. [LOJ#2323]「清华集训 2017」小Y和地铁

    [LOJ#2323]「清华集训 2017」小Y和地铁 试题描述 小Y是一个爱好旅行的OIer.一天,她来到了一个新的城市.由于不熟悉那里的交通系统,她选择了坐地铁. 她发现每条地铁线路可以看成平面上的 ...

  8. 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)

    [UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...

  9. loj2324 「清华集训 2017」小 Y 和二叉树

    https://loj.ac/problem/2324 太智障,一开始以为中序遍历的第一个点一定是一个叶子,想了个贪心.然而,手算了一下,第一个点都过不了啊. input 5 2 3 4 1 3 3 ...

随机推荐

  1. python 编程测试练习2

    1.将A.txt(多行)文件的内容读取出来写入到B.txt中 2.总结 一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法. 1.得到当前工作目录,即当前Python脚 ...

  2. Java里\r \n \t

    \t 相当于tab,缩进 \n 回车 \r 换行 使用来格式化输出的,如:System.out.printf("11111\t2222222");上面的输出的效果就是在11111与 ...

  3. ubuntu16.04 安装以及要做的事情

    1.安装ubuntu 选择安装时更新,以及MP3.图形等:然后选择分区(ext4)(安装时需先进入虚拟系统连上网,输入清华net账号),分区情况按照下图来,swap为临时用的内存分区,可以不要: 选择 ...

  4. UVA-11324 The Largest Clique (强连通+DP)

    题目大意:在一张无向图中,最大的节点集使得集合内任意两个节点都能到达对方. 题目分析:找出所有的强连通分量,将每一个分量视作大节点,则原图变成了一张DAG.将每个分量中的节点个数作为节点权值,题目便转 ...

  5. MySQL中文入库问题

    中文测试没有问题了,此处bug源于MySQL自身编码的问题,创建数据库默认指定相关编码即可. 创建数据库时,指定utf8编码 CREATE DATABASE mydb DEFAULT CHARACTE ...

  6. C#_串口通信_SerialPort_一个最基础的串口程序

    一个最最基础的 串口通信 程序!!! 最近正在学c#_还不是很熟悉_只是有点java的基础 SerialPort类 的介绍 http://msdn.microsoft.com/zh-cn/librar ...

  7. pxe自动安装

    首先我们要用到的linux的桌面模式,没有桌面模式的请自觉安装.注意要关闭防火墙 需要的支持环境,dhcp,tftp,vsftp. 1.先创建ftp的共享光盘目录 mkdir -p /var/ftp/ ...

  8. 使用 Express 实现一个简单的 SPA 静态资源服务器

    背景 限制 SPA 应用已经成为主流,在项目开发阶段产品经理和后端开发同学经常要查看前端页面,下面就是我们团队常用的使用 express 搭建的 SPA 静态资源服务器方案. 为 SPA 应用添加入口 ...

  9. Server.Transfer 页面之间传值

    server.transfer 特点: 1:大家熟悉的一个特点,用server.transfer 跳转到新页面时,浏览器的地址是没有改变的(因为重定向完全在服务器端进行,浏览器根本不知道服务器已经执行 ...

  10. javascript 事件委托 event delegation

    事件委托 event delegation 一.概念: 假设我们有很多个子元素,每个元素被点击时都会触发相应事件,普通的做法是给每个子元素添加一个事件监听. 而,事件委托则是给它们的父元素添加一个事件 ...