[清华集训]小 Y 和恐怖的奴隶主
题面在这里
题意
有一个\(Boss\)和他血量为\(m\)的随从奴隶主,每当奴隶主受到攻击且不死,并且\(Boss\)的随从个数\(<k\)时,就会新召唤一个血量为\(m\)的奴隶主。每次攻击\(Boss\)和每个奴隶主的概率是相同的,求\(n\)步后期望对\(Boss\)造成的伤害。
\(T\le1000,n\le10^{18},m\le3,k\le8\)
sol
看到\(m<=3,k<=8\)的良心数据肯定是状压啦
通过暴搜可以得出状态最多只会有\(164\)种
并且两个状态之间的转移是固定的
因此我们考虑矩阵快速幂
但是...时间复杂度为\(O(T164^3logn)\)跑得过?
因此,优化这种矩乘的方法横空出世:
由于一个向量乘上一个矩阵的复杂度是\(O(n^2)\)的,因此我们把\(2^i\)的矩阵全部预处理出来,
最后再使用倍增的手段进行合并
时间复杂度变成了\(O(164^3logn+T164^2logn)\),非常需要卡常。。。
下面代码不保证能一次通过
代码
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=998244353;
const int N=50010;
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
}
il void file(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
}
ll poww(ll a,ll b){
RG ll ret=1;
for(a%=mod;b;b>>=1,a=a*a%mod)
if(b&1)ret=ret*a%mod;
return ret;
}
ll n,Tim,m,k,ans,tot;
int a[4],t[4];
int b[9][9][9];
struct node{
int x,y,z,id,p;
il void print(){printf("x=%d,y=%d,z=%d,id=%d,p=%d\n",x,y,z,id,p);}
};
vector<node>sol;
int S[170],z[170];
struct matrix{
int a[170][170];
il void clear(){memset(a,0,sizeof(a));}
il void print(){
for(RG int i=1;i<=tot;i++,puts(""))
for(RG int j=1;j<=tot;j++)
printf("%d ",a[i][j]);
puts("");
}
int* operator [](int x){return a[x];}
}T[61],P;
il void dfs(int s[]){
int p[4];
b[s[1]][s[2]][s[3]]=++tot;
P[b[s[1]][s[2]][s[3]]][b[s[1]][s[2]][s[3]]]=poww(s[1]+s[2]+s[3]+1,mod-2)%mod;
sol.pb((node){s[1],s[2],s[3],tot,poww(s[1]+s[2]+s[3]+1,mod-2)});
for(RG int i=1;i<=3;i++)
if(s[i]){//枚举要打的是哪一个
for(RG int j=1;j<=3;j++)p[j]=s[j];
if(s[1]+s[2]+s[3]<k){if(i!=1){p[m]++;p[i-1]++;}p[i]--;}
else{p[i]--;if(i!=1)p[i-1]++;}
RG int add=1ll*s[i]*poww(s[1]+s[2]+s[3]+1,mod-2)%mod;
if(!b[p[1]][p[2]][p[3]])dfs(p);
(P[b[s[1]][s[2]][s[3]]][b[p[1]][p[2]][p[3]]]+=add)%=mod;
}
}
il matrix times1(RG matrix x,RG matrix y){
RG matrix z;z.clear();
for(RG int i=1;i<=tot;i++)
for(RG int j=1;j<=tot;j++)
for(RG int k=1;k<=tot;k++)
z[i][k]=(z[i][k]+1ll*x[i][j]*y[j][k]%mod)%mod;
return z;
}
il void times2(RG matrix y){
memset(z,0,sizeof(z));
for(RG int j=1;j<=tot;j++)
for(RG int k=1;k<=tot;k++)
z[k]=(z[k]+1ll*S[j]*y[j][k]%mod)%mod;
for(RG int i=1;i<=tot;i++)S[i]=z[i];
}
il void DP(ll n){
ans=0;memset(S,0,sizeof(S));S[1]=1;
for(RG ll i=1;(((ll)1)<<(i-1))<=n;i++)
if((n&(((ll)1)<<(i-1)))==(((ll)1)<<(i-1)))
times2(T[i]);
ans=S[tot];
}
int main()
{
file();Tim=read();m=read();k=read();a[m]=1;dfs(a);tot++;
for(RG int i=1;i<=tot-1;i++)P[i][tot]=sol[i-1].p;P[tot][tot]=1;
T[1]=P;for(RG int i=2;i<=60;i++)T[i]=times1(T[i-1],T[i-1]);
while(Tim--){n=read();DP(n);printf("%lld\n",ans);}
return 0;
}
[清华集训]小 Y 和恐怖的奴隶主的更多相关文章
- 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)
[UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...
- loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主
#2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较 题目描述 "A fight? Co ...
- 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法
题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...
- uoj#340. 【清华集训2017】小 Y 和恐怖的奴隶主(矩阵加速)
传送门 uoj上的数据太毒了--也可能是我人傻常数大的缘故-- 三种血量的奴隶主加起来不超过\(8\)个,可以枚举每种血量的奴隶主个数,那么总的状态数只有\(165\)种,设\(dp_{t,i,j,k ...
- 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'}( ...
- LibreOJ #2325. 「清华集训 2017」小Y和恐怖的奴隶主(矩阵快速幂优化DP)
哇这题剧毒,卡了好久常数才过T_T 设$f(i,s)$为到第$i$轮攻击,怪物状态为$s$时对boss的期望伤害,$sum$为状态$s$所表示的怪物个数,得到朴素的DP方程$f(i,s)=\sum \ ...
- 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个 ...
- 洛谷P4007 小 Y 和恐怖的奴隶主(期望dp 矩阵乘法)
题意 题目链接 Sol 首先不难想到一种暴力dp,设\(f[i][a][b][c]\)表示还有\(i\)轮没打,场上有\(a\)个1血,\(b\)个2血,\(c\)个三血 发现状态数只有\(s = 1 ...
随机推荐
- 【css3】旋转倒计时
很多答题的H5界面上有旋转倒计时的效果,一个不断旋转减少的动画,类似于下图的这样. 今天研究了下,可以通过border旋转得到.一般我们可以通过border得到一个四段圆. See the Pen c ...
- 携程Apollo(阿波罗)配置中心在.NET Core项目快速集成
.NET Core的支持文档大体上可以参考文档.Net客户端使用指南:https://github.com/ctripcorp/apollo/wiki/.Net%E5%AE%A2%E6%88%B7%E ...
- Install Centrifugo and quick start
Install Centrifugo and quick start Go is a perfect language - it gives developers an opportunity to ...
- sass 变量
1.使用变量 $符号标识变量 变量名中 中划线和下划线互通(不包括sass中纯 css 部分) 变量值 css 属性标准值 包括以空格 和 逗号 , 分开的多个属性值 变量可以定义在规则块之外
- Docker第一弹:下载运行hello-world程序
1.需要安装好docker程序 没有安装的请看在centos 6.8下安装docker 2.从docker镜像仓库中拉去hello-world镜像 docker pull hello-world 3. ...
- MongoDB入门系列(四):权限管理
一.概述 本篇文章主要介绍如何创建用户和角色相关概念,同时对角色的添加和删除做了相关介绍. 版本:3.6.2 二.角色相关概念 1.数据库用户角色 read:该角色拥有数据的只读权限,系统集合以及sy ...
- 压缩tar命令
option z表示压缩,所以才有后面的.gz, c表示创建这个压缩包,v是可视,能看到其打包和压缩的过程,f表示文件 zcvf 命令格式为 先压缩后跟压缩的目录 tar zcvf /home/xia ...
- ajax的缺点
平时我们大多注意的都是ajax给我们所带来的好处诸如用户体验的提升.对ajax所带来的缺陷有所忽视. 下面所阐述的ajax的缺陷都是它先天所产生的. 1.ajax干掉了back按钮,即对浏览器后退机制 ...
- Django里使用open函数
Django里使用open函数 前言 在Django里使用open函数打开一个文件的时候,常常会遇到路径错误的问题.我在Django APP里写了一个爬虫用于为网站提供数据,但是需要打开文件,也就是在 ...
- SpringMVC的常用注解
在SpringMVC中常用的注解主要都是用于Controller上,所以下面的四大不同类型的注解都是根据它们处理的request的不同内容部分来区分的: 处理requ ...