• 【题解】LOJ #2325 「清华集训 2017」小 Y 和恐怖的奴隶主(矩阵快速幂)


    【题解】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;
    }
    
    
    
  • 相关阅读:
    JS LeetCode 1423. 可获得的最大点数简单题解
    SpringBoot 学集 (第六章) Docker
    Linux 学记 (第三章)
    Linux 学记 (第二章)
    Linux 学记 (第一章)
    SpringBoot 学集 (第五章) Web开发续
    SpringBoot 学集 (第四章)Web开发
    SpringBoot 学集 (第三章) 日志框架
    SpringBoot 学集 (第二章) 配置文件
    SpringBoot 学集 (第一章)
  • 原文地址:https://www.cnblogs.com/winlere/p/13023839.html
Copyright © 2020-2023  润新知