https://www.luogu.com.cn/blog/Thinking/solution-p6630
把节点分为五类
1.不会进入o的父亲且不在祖先终止(与o父亲区间不交)
2.在o打标记终止(包含o但不能包含o的父亲)
3.标记了o的祖先(包含o父亲)
4.下推了o父亲标记但没进入o(与o兄弟有交但与o不交)
5.进入o
记录(f_i)表示(i)有标记概率 (g_i)表示(i)祖先(含(i))有标记概率 矩阵快速幂
#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)putchar('-'),x=-x;
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;
}
inline int ginv(int x){return qpow(x,mod-2);}
struct Mat{
int a11,a12,a13,a22,a23;
inline Mat operator*(const Mat &b)const{
return {a11*b.a11%mod,(a11*b.a12+a12*b.a22)%mod,(a11*b.a13+a12*b.a23+a13)%mod,
a22*b.a22%mod,(a22*b.a23+a23)%mod};
}
};
int ans,inv,n,K;
inline Mat qpow(Mat a,int b){
Mat res={1,0,0,1,0};
for(;b;b>>=1,a=a*a)
if(b&1)res=res*a;
return res;
}
void solve(int L,int R,int l,int r){
if(L<R){
int mid=read();
solve(L,mid,L,R);solve(mid+1,R,L,R);
}
if(!l)tmod(ans+=inv);
else{
int a=(l*(l-1)+(n-r)*(n-r+1)>>1)%mod,
b=(L*(r-R)+(n-R+1)*(L-l))%mod,
c=l*(n-r+1)%mod,
d=((l+L-1)*(L-l)+(n+n-R-r+1)*(r-R)>>1)%mod;
tmod(ans+=qpow({(a+c)*inv%mod,d*inv%mod,b*inv%mod,(a+d)*inv%mod,(b+c)*inv%mod},K).a13);
}
}
main(){
n=read();K=read();inv=ginv(n*(n+1)/2);
solve(1,n,0,0);
printf("%lld
",ans);
return 0;
}