[清华集训]小 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 ...
随机推荐
- WPF项目学习.三
工具代码记录 版权声明:本文为博主初学经验,未经博主允许不得转载. 一.前言 记录在学习与制作WPF过程中遇到的解决方案. 分页控件的制作,邮件发送,日志代码,excel导入导出等代码的实现过程: 二 ...
- 发送POST测试请求的若干方法
最近在工作中需要测试发送带Json格式body值的HTTP POST请求.起初,我在Linux环境下使用curl命令去发送请求,但是,在发送的过程中却遇到了一些问题,经过一段时间的摸索,发现了以下几种 ...
- 根据展示文字自适应 cell 高度,实现点击cell的伸缩扩展
1.要根据展示的文字计算cell的高度, 再此给NSString写的延展的方法, 以此获取展示文字的高度 2.在自定义的cell中 声明属性和定义方法 注:在cell上初始化子控件,最好用代码写, 不 ...
- [记录]Zabbix3.4配置监控Oracle12c的存活状态和表空间使用率
Zabbix3.4配置监控Oracle的存活状态和表空间使用率 1.安装zabbix3.4 agent: # rpm -ivh http://repo.zabbix.com/zabbix/3.4/rh ...
- js中的回调函数
1.你定义的 2.你没有调用 3.但是最终他执行了 例子: 定时器回调函数 setTimeout(function(){ },100); dom元素的回调函数 document.getElementB ...
- filter-api文档
git地址:https://github.com/jiqianqin/filters 不断优化中,欢迎加入讨论- filter-tags 效果图: 参数 说明 格式 备注 data 展示的数据 [{ ...
- length()方法,length属性和size()的方法的区别
length()方法,length属性和size()的方法的区别: length()方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法: length属性是针对Java中的数 ...
- UVA - 1632 Alibaba 区间dp
题意:给定n个点,其中第i个点的坐标是,且它会在秒后消失.Alibaba可以从任意位置出发,求访问完所有点的最短时间.无解输出No solution. 思路:表示访问完区间后停留在i点的最短时间,表示 ...
- 使用org.apache.commons.logging打日志注意事项
使用方法:例如,protected final Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) { lo ...
- hdu1995 汉诺塔V
可以直接把前K-1个罗盘全部忽略了,因为移动前K-1个罗盘不会影响第K个. 也就是相当于只移动剩下的n-k-1个罗盘,当只移动第k个罗盘时,f(k)=1;当要哟东第k个和第k+1个时,就必须先把第k个 ...