今天 T3
T3 稳王
最优策略是:能秒才秒,秒不掉就等着
期望时间可以转成1+第一回合不结束的概率+第二回合不结束的概率+... , 然后转成拿到手里赢不了的牌序列的概率和+1
分类讨论都有什么牌
1.只有复读:不可能赢,\(\sum \frac{1}{3^i}=\frac{1}{2}\)
2.只有毒药,\(n\)张牌以内不可能赢,\(\sum_{i=1}^n \frac{1}{3}\)
3.只有火球,\(m = \lfloor {\frac{n-1}{2}} \rfloor\)牌以内都赢不了,\(\sum_{i=1}^m \frac{1}{3}\)
4.复读+火球:两种牌随便选再减去只有其中一种的,\(\sum_{i=1}^m \frac{2^i-2}{3^i}\)
5.复读+毒药:考虑dp,设\(dp[s]\)表示达到\(s\)点伤害的概率是多少,此种牌型下复读和毒药都是一点伤害,用矩阵转移dp,再减去只有其中一种的
6.毒药+火球:伤害为1+3,做法同5
7.做法类似,先三种随便选,再减去只有其中两种的,再加回来只有一种的
注意我们求的是不结束的概率,在包含一些毒药的部分,有一个我们需要额外多一张毒药的要求,于是当达到n点伤害时我们仍不能胜利,但下一回合必胜。
点击查看代码
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i)
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
#define int ll
using namespace std;
const int maxn=7,Mod=998244353;
int pw(int x,int p){int res=1,base=x;while(p){if(p&1)res=1LL*res*base%Mod;base=1LL*base*base%Mod;p>>=1;}return res;}
int Inv(int x){return pw(x,Mod-2);}
struct Matrix{
int a[maxn][maxn],N;
void Set(int x){N=x;Clear();}
Matrix(){memset(a,0,sizeof(a));}
void Clear(){memset(a,0,sizeof(a));}
void init(){for(int i=1;i<=N;i++)a[i][i]=1;}
Matrix operator*(const Matrix &x)const{
Matrix z;z.Set(N);
for(int i=1;i<=N;i++){
for(int k=1;k<=N;k++){
int r=a[i][k];
for(int j=1;j<=N;j++)z.a[i][j]=(1LL*x.a[k][j]*r%Mod+z.a[i][j])%Mod;
}
}
return z;
}
};
Matrix pw(Matrix x,int p){
Matrix base=x,res;res.Set(x.N);res.init();
while(p){ if(p&1)res=res*base; base=base*base; p>>=1; } return res;
}
int tex,n;
ll ans;
int Calc(int x,int n){ return 1LL*x*(1-pw(x,n))%Mod*Inv((1-x+Mod)%Mod)%Mod; }
void solve(){ans=0;
cin>>n;int m=(n-1)>>1;
//只有复读
{ ans = Inv(2); }
//只有毒药
{ ans = ( ans + ( 1LL * ( 1-Inv( pw(3,n) ) ) * Inv(2) %Mod) )%Mod; }
// cout<<(ans+Mod)%Mod<<"\n";
//只有火球
{ ans = ( ans + ( 1LL * ( 1-Inv( pw(3,m) ) ) * Inv(2) %Mod) )%Mod;}
// cout<<(ans+Mod)%Mod<<"\n";
//复读+火球
{ ans = ( ans + Calc( 2LL*Inv(3)%Mod,m )-2LL*Calc(Inv(3),m) )%Mod; }
// cout<<(ans+Mod)%Mod<<"\n";
n--;
//复读+毒药
{
Matrix G,F;G.Set(3),F.Set(3);
F.a[1][1]=1;
G.a[1][1]=G.a[2][1]=G.a[1][3]=G.a[2][3]=Inv(3);
G.a[1][2]=1;G.a[3][3]=1;
F=F*pw(G,n+1);
ans = ( ans + F.a[1][3] )%Mod;
ans = ( ans - Calc(Inv(3),(n+1)/2) - Calc(Inv(3),n+1) )%Mod;
}
// cout<<(ans+Mod)%Mod<<"\n";
//毒药+火球
{
Matrix G,F;G.Set(4),F.Set(4);
F.a[1][1]=1;
G.a[1][1]=G.a[1][4]=G.a[3][1]=G.a[3][4]=Inv(3);
G.a[1][2]=G.a[2][3]=G.a[4][4]=1;
F=F*pw(G,n+1);
ans = ( ans + F.a[1][4] )%Mod;
ans = ( ans - Calc(Inv(3),n+1) - Calc(Inv(3),(n+1)/3) )%Mod;
}
// cout<<(ans+Mod)%Mod<<"\n";
//三合一
{
{//all
Matrix G,F;G.Set(5),F.Set(5);
F.a[1][1]=1;
G.a[1][1]=G.a[1][5]=G.a[3][1]=G.a[4][1]=G.a[3][5]=G.a[4][5]=Inv(3);
G.a[1][2]=G.a[2][3]=G.a[3][4]=G.a[5][5]=1;
F=F*pw(G,n+1);
ans = ( ans + F.a[1][5] )%Mod;
}
// cout<<(ans+Mod)%Mod<<"\n";
{//毒药+火球
Matrix G,F;G.Set(5);F.Set(5);
F.a[1][1]=1;
G.a[1][1]=G.a[1][5]=G.a[3][1]=G.a[3][5]=Inv(3);
G.a[1][2]=G.a[2][3]=G.a[3][4]=G.a[5][5]=1;
F=F*pw(G,n+1);
ans = ( ans - F.a[1][5] )%Mod;
}
// cout<<(ans+Mod)%Mod<<"\n";
{//毒药+复读
Matrix G,F;G.Set(5),F.Set(5);
F.a[1][1]=1;
G.a[1][1]=G.a[1][5]=G.a[4][1]=G.a[4][5]=Inv(3);
G.a[1][2]=G.a[2][3]=G.a[3][4]=G.a[5][5]=1;
F=F*pw(G,n+1);
ans = ( ans - F.a[1][5] )%Mod;
}
// cout<<(ans+Mod)%Mod<<"\n";
{//复读+火球
Matrix G,F;G.Set(5),F.Set(5);
F.a[1][1]=1;
G.a[3][1]=G.a[4][1]=G.a[3][5]=G.a[4][5]=Inv(3);
G.a[1][2]=G.a[2][3]=G.a[3][4]=G.a[5][5]=1;
F=F*pw(G,n+1);
ans = ( ans - F.a[1][5] )%Mod;
}
// cout<<(ans+Mod)%Mod<<"\n";
ans = ( ans + Calc(Inv(3),n+1) )%Mod;
ans = ( ans + Calc(Inv(3),(n+1)/3) )%Mod;
ans = ( ans + Calc(Inv(3),(n+1)/4) )%Mod;
}
cout <<((ans%Mod+Mod)%Mod+1)%Mod<<"\n";
}
#undef int
int main (){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);fre(stable);cin>>tex;while(tex--)solve(); }