[清华集训]小 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 ...
随机推荐
- ThreadLocal 简述
ThreadLocal的理解 Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量.因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们 ...
- ConcurrentHashMap源码分析(一)
本篇博客的目录: 前言 一:ConcurrentHashMap简介 二:ConcurrentHashMap的内部实现 三:总结 前言:HashMap很多人都熟悉吧,它是我们平时编程中高频率出现的一种集 ...
- Linux中的 awk查找日志中的相关记录
假设要在 api.log.201707201830 文件中,(此文件的多个字段数据以不可见字符^A(键盘上按下Ctrl+V+A)分隔),要输出第70个字段: awk -F '^A' '{print $ ...
- JVM自动内存管理-Java内存区域与内存溢出异常
摘要: JVM内存的划分,导致内存溢出异常的可能区域. 1. JVM运行时内存区域 JVM在执行Java程序的过程中会把它所管理的内存划分为以下几个区域: 1.1 程序计数器 程序计数器是一块较小的内 ...
- go 开发环境安装教程 windows
首先进入go 语言官网下载最新安装包,我目前安装的版本是 1.8.3版本:go1.8.3.windows-amd64.msi 如果下载慢,这个是百度云地址:https://pan.baidu ...
- prop&attr区别和用法,以多选框为例
1.比较 相同点 : prop和attr作为jquery的方法都可以获取属性值; 不同点 : (1) 对于HTML元素本身就带有的固有属性,使用prop方法, attr获取checkbox的check ...
- Qt 动态加载DLL 常见错误有哪些?
1. dll 路径不对,比如 IE 中 2. 依赖库缺失,会报错找不到指定模块 注意: qt 的 qlibrary 只能加载 标准 C 函数
- SpringBoot中关于Mybatis使用的三个问题
SpringBoot中关于Mybatis使用的三个问题 转载请注明源地址:http://www.cnblogs.com/funnyzpc/p/8495453.html 原本是要讲讲PostgreSQL ...
- React——diff算法
react的diff算法基于两个假设: 1.不同类型的元素会产生不同的树 2.通过设置key,开发者能够提示那些子组件是稳定的 diff算法 当比较两个树时,react首先会比较两个根节点,接下来具体 ...
- Nginx反向代理实现Tomcat负载均衡
这篇短文主要介绍Tomcat的集群和用Nginx反向代理实现Tomcat负载均衡. 1.首先需要对一些知识点进行扫盲(对自己进行扫盲,囧): 集群(Cluster) 简单来说就是用N台服务器构成一个松 ...