设(dp_{i,a,b,c})表示前(i)次攻击,场上有(a)个一血 (b)个二血 (c) 个三血的概率
还要再记一个(g_i)表示前(i)次对boss期望伤害
算上(g)总共166个状态 可以矩阵快速幂了
预处理矩阵的(2^k) 询问的时候只需要用一个行向量乘log个矩阵
时间复杂度变为(O(T166^2logn))
#include<bits/stdc++.h>
using namespace std;
#define fp(i,l,r) for(register int (i)=(l);(i)<=(r);++(i))
#define fd(i,l,r) for(register int (i)=(l);(i)>=(r);--(i))
#define fe(i,u) for(register int (i)=front[(u)];(i);(i)=e[(i)].next)
#define mem(a) memset((a),0,sizeof (a))
#define O(x) cerr<<#x<<':'<<x<<endl
#define int long long
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
void wr(int x){
if(x<0)x=-x,putchar('-');
if(x>=10)wr(x/10);
putchar('0'+x%10);
}
const int mod=998244353;
inline void tmod(int &x){x%=mod;}
inline int qpow(int a,int b){
int res=1;a%=mod;
for(;b;b>>=1,tmod(a*=a))
if(b&1)tmod(res*=a);
return res;
}
int id[9][9][9],cnt,T,m,K;
struct Mat{
int a[170][170];
Mat(){mem(a);}
inline int *operator[](int x){return a[x];}
inline friend Mat operator*(Mat a,Mat b){
Mat c;
fp(i,1,cnt)fp(j,1,cnt){
__int128 t=0;
fp(k,1,cnt)t+=a[i][k]*b[k][j];
c[i][j]=t%mod;
}
return c;
}
}s[60];
int ans[170],tmp[170];
inline void Mul(Mat c){
mem(tmp);
fp(i,1,cnt){
__int128 t=0;
fp(j,1,cnt)t+=c[j][i]*ans[j];
tmp[i]=t%mod;
}
fp(i,1,cnt)ans[i]=tmp[i];
}
main(){
T=read();m=read();K=read();
fp(i,0,K)
fp(j,0,m>=2?K-i:0)
fp(k,0,m>=3?K-i-j:0)
id[i][j][k]=++cnt;
++cnt;s[0][cnt][cnt]=1;
fp(a,0,K)fp(b,0,m>=2?K-a:0)fp(c,0,m>=3?K-a-b:0){
int t=id[a][b][c],iv=qpow(a+b+c+1,mod-2),ext=a+b+c<K;
if(a)s[0][t][id[a-1][b][c]]=a*iv%mod;
if(m==2&&b)s[0][t][id[a+1][b-1+ext][c]]=b*iv%mod;
if(m==3&&b)s[0][t][id[a+1][b-1][c+ext]]=b*iv%mod;
if(m==3&&c)s[0][t][id[a][b+1][c-1+ext]]=c*iv%mod;
s[0][t][cnt]=s[0][t][t]=iv;
}
fp(i,1,59)s[i]=s[i-1]*s[i-1];
while(T--){
int x=read();
mem(ans);ans[id[m==1][m==2][m==3]]=1;
fp(i,0,59)if(x>>i&1)Mul(s[i]);
printf("%lld
",ans[cnt]);
}
return 0;
}