【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)
【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)
题面
题解
考虑如何暴力\(dp\)。
设\(f[i][a][b][c]\)表示当前到了第\(i\)次攻击,还剩下的\(1,2,3\)血的奴隶主个数为\(a,b,c\)的概率,每次考虑打到了哪里,做一个转移。
这样子,状态数就是把不超过\(8\)个东西分配到\(3\)个集合中,状态有\(165\)种,再加一个状态记录糊脸上的期望,也就是\(166\)个状态。
直接矩乘优化,那么单次的复杂度就是\(O(166^3*log n)\),显然过不了。
把\(2^k\)的矩阵预处理出来,每次拿行向量去乘矩阵,优化到\(O(166^2*log n)\)
然后就卡卡卡卡卡卡常吧。
提供几个卡常方式:
- 数组卡着数据范围开
- 随时交换循环顺序
- 手动矩乘
#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
#define MOD 998244353
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
inline ll read()
{
ll x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int m,K;ll n;
int bh[9][9][9],tot,lim[5];
int inv[20];
int P[61][170][170];
int A[170],tmp[170],Ans[170];
void dfs(int a,int b,int c)
{
if(a>lim[1]||b>lim[2]||c>lim[3])return;
if(bh[a][b][c]||a+b+c>K)return;
bh[a][b][c]=++tot;
dfs(a+1,b,c);dfs(a,b+1,c);dfs(a,b,c+1);
}
void Plus(int &A,int &B,int &C){if(m==1)++A;if(m==2)++B;if(m==3)++C;}
void pre()
{
inv[0]=inv[1]=1;for(int i=2;i<20;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int a=0;a<=K&&a<=lim[1];++a)
for(int b=0;a+b<=K&&b<=lim[2];++b)
for(int c=0;a+b+c<=K&&c<=lim[3];++c)
{
int s=a+b+c+1,p=bh[a][b][c];
add(P[0][p][tot+1],inv[s]);add(P[0][p][p],inv[s]);
if(a)P[0][p][bh[a-1][b][c]]=(P[0][p][bh[a-1][b][c]]+1ll*a*inv[s])%MOD;
if(b)
{
int A=a+1,B=b-1,C=c;if(s<=K)Plus(A,B,C);
P[0][p][bh[A][B][C]]=(P[0][p][bh[A][B][C]]+1ll*b*inv[s])%MOD;
}
if(c)
{
int A=a,B=b+1,C=c-1;if(s<=K)Plus(A,B,C);
P[0][p][bh[A][B][C]]=(P[0][p][bh[A][B][C]]+1ll*c*inv[s])%MOD;
}
}
add(P[0][tot+1][tot+1],1);
A[bh[m==1][m==2][m==3]]=1;
for(int p=1;p<=60;++p)
for(int i=1;i<=tot+1;++i)
for(int k=1;k<=tot+1;++k)
for(int j=1;j<=tot+1;++j)
P[p][i][j]=(P[p][i][j]+1ll*P[p-1][i][k]*P[p-1][k][j])%MOD;
}
int main()
{
int T=read();m=read();K=read();
for(int i=1;i<=m;++i)lim[i]=K;
dfs(0,0,0);pre();
while(T--)
{
n=read();int p=0;
for(int i=1;i<=tot+1;++i)Ans[i]=A[i];
while(n)
{
if(n&1)
{
for(int i=1;i<=tot+1;++i)tmp[i]=Ans[i],Ans[i]=0;
for(int k=1;k<=tot+1;++k)
for(int j=1;j<=tot+1;++j)
Ans[j]=(Ans[j]+1ll*tmp[k]*P[p][k][j])%MOD;
}
++p;n>>=1;
}
printf("%d\n",Ans[tot+1]);
}
return 0;
}
【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)的更多相关文章
- [清华集训2017]小 Y 和地铁(神奇思路,搜索,剪枝,树状数组)
世界上最不缺的就是好题. 首先考虑暴搜.(还有什么题是从这东西推到正解的……) 首先单独一个换乘站明显没用,只用考虑一对对的换乘站. 那么有八种情况:(从题解偷图) 然后大力枚举每个换 ...
- loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主
#2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较 题目描述 "A fight? Co ...
- [清华集训]小 Y 和恐怖的奴隶主
题面在这里 题意 有一个\(Boss\)和他血量为\(m\)的随从奴隶主,每当奴隶主受到攻击且不死,并且\(Boss\)的随从个数\(<k\)时,就会新召唤一个血量为\(m\)的奴隶主.每次攻击 ...
- 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法
题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...
- uoj#340. 【清华集训2017】小 Y 和恐怖的奴隶主(矩阵加速)
传送门 uoj上的数据太毒了--也可能是我人傻常数大的缘故-- 三种血量的奴隶主加起来不超过\(8\)个,可以枚举每种血量的奴隶主个数,那么总的状态数只有\(165\)种,设\(dp_{t,i,j,k ...
- 2018.10.16 uoj#340. 【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂优化dp)
传送门 一道不错的矩阵快速幂优化dpdpdp. 设f[i][j][k][l]f[i][j][k][l]f[i][j][k][l]表示前iii轮第iii轮还有jjj个一滴血的,kkk个两滴血的,lll个 ...
- LibreOJ #2325. 「清华集训 2017」小Y和恐怖的奴隶主(矩阵快速幂优化DP)
哇这题剧毒,卡了好久常数才过T_T 设$f(i,s)$为到第$i$轮攻击,怪物状态为$s$时对boss的期望伤害,$sum$为状态$s$所表示的怪物个数,得到朴素的DP方程$f(i,s)=\sum \ ...
- LOJ2325. 「清华集训 2017」小 Y 和恐怖的奴隶主【矩阵快速幂优化DP】【倍增优化】
LINK 思路 首先是考虑怎么设计dp的状态 发现奴隶主的顺序没有影响,只有生命和个数有影响,所以就可以把每个生命值的奴隶主有多少压缩成状态就可以了 然后发现无论是什么时候一个状态到另一个状态的转移都 ...
- LOJ2325「清华集训 2017」小Y和恐怖的奴隶主
题目链接 首先dp很显然,\(f(i,s)\)表示到了第i轮,各种血量人数的情况为s今后的期望攻击boss次数.那么有\(f(i,s)=\frac{1}{num+1}*\sum_{s->s'}( ...
随机推荐
- 解决只能root权限登陆mysql的问题
一.问题描述 在用sqoop连接mysql时,会报错如下图所示,原因是mysql在默认情况下是使用了auth_socket plugin进行认证,即每次登陆都需要sudo mysql -u local ...
- pip Read timed out 和 pip 源
解决方法,设置超时时间 pip --default-timeout=100 install -U Pillow 安装时指定源(--index-url) #例如安装scipy时使用豆瓣的源 pip in ...
- php常用方法
在日常开发中,经常我们使用系统方法或者是自己封装的方法进行项目的开发.再此总结一下!!! 一.对于字符串截取 1.使用mbstring扩展 (注意编码的设置) mb_substr($str,2,5, ...
- React Native之获取通讯录信息并实现类通讯录列表(ios android)
React Native之获取通讯录信息并实现类通讯录列表(ios android) 一,需求分析 1,获取通讯录信息,筛选出通讯录里有多少好友在使用某个应用. 2,获取通讯录信息,实现类通讯录,可拨 ...
- mysql中的几种日志了解
前言 MySQL中有以下日志文件,分别是: 1:重做日志(redo log) 2:回滚日志(undo log) 3:二进制日志(binlog) 4:错误日志(errorlog) 5:慢查询日志(slo ...
- [官网]Red Hat Enterprise Linux Release Dates
Red Hat Enterprise Linux Release Dates https://access.redhat.com/articles/3078 The tables below list ...
- Docker入门了解一下(第一篇)
最近在学docker.k8s什么的,看得脑子有点乱.从来没弄过在linux上搭建一个分布式的环境,所以对这些不太了解,还是从最简单的地方剖析吧. Docker学习传送:http://www.ityou ...
- day 7-3 僵尸进程,孤儿进程与守护进程
一.基本定义 正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一个 进程完成它的工作终止之后,它 ...
- 二进制安装MongoDB
1.下载mongodb cd /usr/local/src/ wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.5.tgz ...
- HeapSter安装(k8s1.12以后废弃了)
HeapSter InfluxDB(持久存储) Grafana 展示InfluxDB的数据(类似kibana) #安装InfluxDB #github https://github.com/kuber ...