[清华集训]小 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 ...
随机推荐
- 低版本IE内核浏览器兼容placeholder属性解决办法
最简便的一个方法,通过js实现. <input type="text" name="username" id="username" v ...
- [UWP]做个调皮的BusyIndicator
1. 前言 最近突然想要个BusyIndicator.做过WPF开发的程序员对BusyIndicator应该不陌生,Extended WPF Toolkit 提供了BusyIndicator的开源实现 ...
- 记一次内存溢出的分析经历——thrift带给我的痛orz
说在前面的话 朋友,你经历过部署好的服务突然内存溢出吗? 你经历过没有看过Java虚拟机,来解决内存溢出的痛苦吗? 你经历过一个BUG,百思不得其解,头发一根一根脱落的烦恼吗? 我知道,你有过! 但是 ...
- 如何使用 OpenCV 打开摄像头获取图像数据?
OpenCV 如何打开摄像头获取图像数据? 代码运行环境:Qt 5.9.1 msvc2015 32bit OpenCV 3.3.0 #include "include/opencv2/ope ...
- hdu 2048 递推&&错排
直接贴出递推公式: cnt[n]=(i-1)*(cnt[n-1]+cnt[n-2]); 数组保存的是失败的种数 AC代码: #include<cstdio> const int maxn= ...
- SpringBoot整合SpringSecurity,SESSION 并发管理,同账号只允许登录一次
重写了UsernamePasswordAuthenticationFilter,里面继承AbstractAuthenticationProcessingFilter,这个类里面的session认证策略 ...
- Mybatis的基本使用
.什么是Mybatis? Mybatis:根据官方解释,MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及 ...
- Docker系列二:Docker的基本结构
Docker的基本结构 Docker 的三大基础组件 Docker有三个重要的概念:仓库 , 镜像 和 容器 ,它们是Docker的三大基出组件 Docker的组织结构 Docker处于操作系统和虚拟 ...
- session 与 coolie 的区别与联系
cookie 和session 的区别: session 在服务器端,cookie 在客户端(浏览器) cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当 ...
- 禁掉coolie,session还能正常使用吗?
Cookie禁用了,Session还能用吗? Cookie与 Session,一般认为是两个独立的东西,Session采用的是在服务器端保持状态的方案,而Cookie采用的是在客户端保持状态的方案 ...