【题解】LOJ #2325 「清华集训 2017」小 Y 和恐怖的奴隶主(矩阵快速幂)
设(f(i,a,b,c))表示进行到(i)次攻击,血量分别为(1,2,3)的怪的数量为(a,b,c)的概率。如果你设表示攻击boss的次数期望的话就还要而外记录一个概率,不然无法转移,所以不如直接设成概率,每次转移(f(i,a,b,c) o f(i+1,a,b,c))的时候叠加一下答案即可(贡献为(f(i,a,b,c)over a+b+c+1)),可以看做是(ans(i)=ans(i-1)+sum {f(i,a,b,c)over a+b+c+1}),和(f)一起dp即可。
状态数乍一看是(8^3),但是考虑到(a+b+cle 8),也就是方程(x_1+x_2+x_3+x_4=8)的解的个数,解的数量是({4+8-1choose 8}=165)。
那么考虑矩阵快速幂就好了,注意到询问次数比较多,用向量优化的方法就行了。
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
inline ll qr(){
ll ret=0,f=0,c=getchar();
while(!isdigit(c)) f|=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int mod=998244353;
int MOD(const int&x){return x>=mod?x-mod:x;}
int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
int st[10][10][10],vec[maxn],temp[maxn],id;
// 1(a)2(b)3(c)
const int maxn=166;
struct{int x,y,z;}rem[maxn];
struct MAT{
int v[maxn][maxn];
MAT(){memset(v,0,sizeof(int)*maxn*maxn);}
int* operator [](const int&x){return v[x];};
MAT operator * (const MAT&x)const{
MAT ret;
for(int k=0;k<=id;++k)
for(int t=0;t<=id;++t)
for(int i=0;i<=id;++i)
ret[t][i]=MOD(ret[t][i]+MOD(v[t][k],x.v[k][i]));
return ret;
}
}mi[61];
int ksm(const int&ba,const int&p){
int ret=1;
for(int t=p,b=ba;t;t>>=1,b=MOD(b,b))
if(t&1) ret=MOD(ret,b);
return ret;
}
int main(){
int T=qr(),m=qr(),k=qr();
for(int a=0;a<=k;++a)
for(int b=0;(b+a<=k&&m>=2)||b==0;++b)
for(int c=0;(a+b+c<=k&&m>=3)||c==0;++c)
rem[id]={a,b,c},st[a][b][c]=id++;
for(int t=0;t<id;++t){
int a=rem[t].x,b=rem[t].y,c=rem[t].z,inv=ksm(a+b+c+1,mod-2);
//hit boss
mi[0][t][t]=inv;
mi[0][t][id]=inv;
//hit a (1 hp)
if(a) mi[0][t][st[a-1][b][c]]=MOD(a,inv);
//hit b (2 hp)
if(b) mi[0][t][st[a+1][b-1+(a+b<k&&m==2)][c+(a+b+c<k&&m==3)]]=MOD(b,inv);
//hit c (3 hp)
if(c) mi[0][t][st[a][b+1][c-1+(a+b+c<k)]]=MOD(c,inv);
}
mi[0][id][id]=1;
for(int t=1;t<=60;++t) mi[t]=mi[t-1]*mi[t-1];
while(T--){
memset(vec,0,sizeof vec);
ll n=qr();
vec[st[m==1][m==2][m==3]]=1;
for(int t=0;t<=60;++t,n>>=1)
if(n&1){
memcpy(temp,vec,sizeof vec);
memset(vec,0,sizeof vec);
for(int j=0;j<=id;++j)
for(int i=0;i<=id;++i)
vec[i]=MOD(vec[i]+MOD(mi[t][j][i],temp[j]));
}
printf("%d
",vec[id]);
}
return 0;
}