[清华集训]小 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 ...
随机推荐
- Python面向对象篇(3)-封装、多态、反射及描述符
1. 多态 多态,最浅显的意识就是同一事物具有多种形态,这很好理解,动物是一个大类,猫类属于动物类,狗类属于动物类,人也是属于动物类,那能理解成,猫.狗.人是一样的吗?当然不是,还有,水,分为液体.固 ...
- Redis进阶实践之十二 Redis的Cluster集群动态扩容
一.引言 上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cl ...
- Windows Server 2016-存储新增功能
本章给大家介绍有关Windows Server 2016 中存储方面的新增功能,具体内容如下: 1.Storage Spaces Direct: 存储空间直通允许通过使用具有本地存储的服务器构建高可用 ...
- GCC精彩之旅_2(转)
说明: 本文共两篇,转自GCC精彩之旅.第一篇着重介绍GCC编译一个程序的过程与优化,第二篇侧重在GCC结合GDB对代码的调试. 调试 一个功能强大的调试器不仅为程序员提供了跟踪程序执行的手段 ...
- 关于HTTP,你知道哪些?
HTTP简介 HTTP 的全称是 Hypertext Transfer Protocol,超文本传输协议 规定客户端和服务器之间的数据传输格式 让客户端和服务器能有效地进行数据沟通 HTTP 协议是网 ...
- UVA - 1631 Locker 记忆化搜索
题意:给定两个密码串,每次可以让1~3个相邻的密码向上或者向下滚动,每个密码是 ,问最少需要多少次滚动可以让原串成为目标串? 思路:假设当前要让第i位密码还原,我们可以同时转动,不同的转动方式会影响后 ...
- ACdream 1015 Double Kings 树的重心
思路:删除根结点,其最大子树的节点最少.求一次树的重心即可. AC代码 #include <cstdio> #include <cmath> #include <ccty ...
- nyoj737 石子合并(一) 区间DP
dp[x][y]表示合并[x, y]区间的石子的最小花费,将区间长度递增枚举即可. AC代码: #include<cstdio> #include<algorithm> usi ...
- 在SpringBoot中使用FluentValidator验证插件
前言 在我们编写项目的时候,在controller中往往离不开对一些数据的校验.这里并不是说对于这些数据业务上面的校验,而是对这些数据进行空校验或者是长度校验等. 有些时候校验可以省略,根据业务的需要 ...
- HDFS读写过程
HDFS的读写过程: 读过程: Client收到用户的读请求——client拿着path向namenode请求文件或者block的datanode列表——client从返回的datanode列表中选择 ...