题目链接

首先dp很显然,\(f(i,s)\)表示到了第i轮,各种血量人数的情况为s今后的期望攻击boss次数。那么有\(f(i,s)=\frac{1}{num+1}*\sum_{s->s'}(f(i+1,s')+0/1)\),num为奴隶主个数,当攻击boss时后面的贡献就是1,否则是0,s可以用一个m位k+1进制数来表示(代表血量为1,2,3的奴隶主个数)。

然后处理出s的转移需要哪些状态(总状态数为\(tot=C_{10}^2+C_9^2+...+C_2^2=165\)),那么可以矩乘优化了。由于有多组询问,因此可以预处理出矩阵的\(2^k\)次方,但由于这样做询问时的复杂度还是\(O(tot^3logn)\)的,我们想到最边上的矩阵是\(tot*1\)的,且一个\(tot*tot\)的矩阵与\(tot*1\)的矩阵乘出来还是\(tot*1\)的,因此可以从\(tot*1\)的矩阵开始一路向左乘,这样复杂度就是\(O(tot^2logn)\)的。

总复杂度\(O(tot^3logn+T*tot^2logn)\),矩乘那里需要卡卡常。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#define P puts("lala")
#define cp cerr<<"lala"<<endl
#define ln putchar('\n')
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
inline int read()
{
char ch=getchar();int g=1,re=0;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
return re*g;
}
typedef long long ll;
typedef pair<int,int> pii; const int N=201;
const int mod=998244353;
const ll MOD=(0x7fffffffffffffffll/mod-mod)*mod;
const ll MAXN=1e18;
const int maxb=59;
ll qpow(ll a,int n)
{
ll ans=1;
for(;n;n>>=1,a=a*a%mod) if(n&1) ans=ans*a%mod;
return ans;
}
struct mat
{
int n,m;
int s[169][169];
mat() {clean();}
void clean() {memset(s,0,sizeof(s));n=m=0;}
};
mat c;
ll tmp[169][169];
mat operator * (const mat &a,const mat &b)
{
c.n=a.n; c.m=b.m;
for(int i=0;i<a.n;++i) for(int k=0;k<a.m;++k)
{
if(!a.s[i][k]) continue;
for(int j=0;j<b.m;++j) if((tmp[i][j]+=1ll*a.s[i][k]*b.s[k][j])>=MOD)
tmp[i][j]-=MOD;
//c.s[i][j]=(c.s[i][j]+1ll*a.s[i][k]*b.s[k][j]%mod)%mod;
}
for(int i=0;i<c.n;++i) for(int j=0;j<c.m;++j)
c.s[i][j]=tmp[i][j]%mod,tmp[i][j]=0;
return c;
}
mat matpw[70],X,V;
int id[N],is[N],tot=0,pw[15],K,m,k;
ll n; void wj()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
}
int main()
{
wj();
int i,j,opt,T;
T=read(); m=read(); k=read();
K=k+1; pw[0]=1;
for(i=1;i<=m;++i) pw[i]=pw[i-1]*K;
for(i=0;i<pw[m];++i)
{
int s=0;
for(j=0;j<m;++j) s+=i/pw[j]%K;
if(s<=k) is[tot]=i,id[i]=tot,tot++;
}
X.n=tot+1; X.m=1;
X.s[tot][0]=1; matpw[0].n=matpw[0].m=tot+1;
matpw[0].s[tot][tot]=1;
for(int idx=0;idx<tot;++idx)
{
int num=0;
for(i=0;i<m;++i) num+=is[idx]/pw[i]%K;
int inv=qpow(num+1,mod-2);
matpw[0].s[idx][tot]=inv; matpw[0].s[idx][idx]=inv;
int x=is[idx];
for(i=0;i<m;++i) if(x/pw[i]%K)
{
x-=pw[i];
if(i) x+=pw[i-1];
if(i&&num<k) x+=pw[m-1];
(matpw[0].s[idx][id[x]]+=1ll*inv*(is[idx]/pw[i]%K)%mod)%=mod;
x=is[idx];
}
}
for(i=1;i<=maxb;++i) matpw[i]=matpw[i-1]*matpw[i-1];
int ans=pw[m-1];
for(int cas=1;cas<=T;++cas)
{
scanf("%lld",&n);
V=X;
for(i=0;i<=maxb;++i) if(n&(1ll<<i)) V=matpw[i]*V;
printf("%d\n",V.s[id[ans]][0]);
}
return 0;
}

LOJ2325「清华集训 2017」小Y和恐怖的奴隶主的更多相关文章

  1. LOJ2325. 「清华集训 2017」小 Y 和恐怖的奴隶主【矩阵快速幂优化DP】【倍增优化】

    LINK 思路 首先是考虑怎么设计dp的状态 发现奴隶主的顺序没有影响,只有生命和个数有影响,所以就可以把每个生命值的奴隶主有多少压缩成状态就可以了 然后发现无论是什么时候一个状态到另一个状态的转移都 ...

  2. loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主

    #2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较   题目描述 "A fight? Co ...

  3. 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法

    题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...

  4. LibreOJ #2325. 「清华集训 2017」小Y和恐怖的奴隶主(矩阵快速幂优化DP)

    哇这题剧毒,卡了好久常数才过T_T 设$f(i,s)$为到第$i$轮攻击,怪物状态为$s$时对boss的期望伤害,$sum$为状态$s$所表示的怪物个数,得到朴素的DP方程$f(i,s)=\sum \ ...

  5. Loj #2324. 「清华集训 2017」小 Y 和二叉树

    Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...

  6. [LOJ#2324]「清华集训 2017」小Y和二叉树

    [LOJ#2324]「清华集训 2017」小Y和二叉树 试题描述 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙 ...

  7. [LOJ#2323]「清华集训 2017」小Y和地铁

    [LOJ#2323]「清华集训 2017」小Y和地铁 试题描述 小Y是一个爱好旅行的OIer.一天,她来到了一个新的城市.由于不熟悉那里的交通系统,她选择了坐地铁. 她发现每条地铁线路可以看成平面上的 ...

  8. 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)

    [UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...

  9. loj2324 「清华集训 2017」小 Y 和二叉树

    https://loj.ac/problem/2324 太智障,一开始以为中序遍历的第一个点一定是一个叶子,想了个贪心.然而,手算了一下,第一个点都过不了啊. input 5 2 3 4 1 3 3 ...

随机推荐

  1. ViewPlane类定义

    这个类主要是记录了所有跟视图窗口有关的数据,用于显示. 类声明: #pragma once #ifndef __VIEWPLANE_HEADER__ #define __VIEWPLANE_HEADE ...

  2. java-Collection,List简单使用与方法/(集合使用-中)

    1.1集合只存放引用类型的元素并且集合存放的时元素的引用(地址)1.2新循环遍历集合 Collection c = new ArrayList(); c.add("one"); c ...

  3. 最大连续子序列(简单DP实现)

    最大连续子序列 最大连续子数列和一道很经典的算法问题,给定一个数列,其中可能有正数也可能有负数,我们的任务是找出其中连续的一个子数列(不允许空序列),使它们的和尽可能大.我们一起用多种方式,逐步优化解 ...

  4. 1.6_HTML基础属性

    name 属性 name 属性用于指定标签元素的名称. <a> 标签内必须提供 href 或 name 属性. <a name="value"> id 属性 ...

  5. 字节跳动端智能工程链路 Pitaya 的架构设计

    Client AI 是字节跳动产研架构下属的端智能团队,负责端智能 AI 框架和平台的建设,也负责模型和算法的研发,为字节跳动开拓端上智能新场景.本文介绍的 Pitaya 是由字节跳动的 Client ...

  6. Python 爬取网站数据

    一.使用request库实现批量下载HTML 二.使用BeautifulSoup库实现html解析 官网:https://beautifulsoup.readthedocs.io/zh_CN/v4.4 ...

  7. flex常用布局

    公共样式: <style> * { margin: 0; padding: 0; } .has-flex { display: flex; } </style> 垂直居中 子元 ...

  8. mybatis_config xml配置

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC ...

  9. SpringBoot Xml转Json对象

    一.导入需要的依赖 <dependency> <groupId>maven</groupId> <artifactId>dom4j</artifa ...

  10. [BJDCTF2020]Easy MD5 WP

    老样子 打开看看 你会发现 啥也没有 有一个输入框,随便输入看看 抓包发现跳转leveldo4.php 同时看到 hint 里面有select * from 'admin' where passwor ...