luogu P6630 [ZJOI2020] 传统艺能
题面传送门
ZJOI:我抄我自己。
首先这个题\(k=1\)和ZJOI2019基本是一样的。
我们考虑每个点成为五类点的概率。
第一种:走到但是不包含,不会算所以用一减去剩下所有类。
第二种:走到且全包含,就是包含当前区间且不包含父亲区间。
第三种:走不到但是全包含就是父亲的第二种加上父亲的第三种,也就是父亲就走不到和走到父亲就停了。
第四种:走不到,不包含且有pushdown,就是父亲走得到且单侧递归。
第五种:走不到,不包含且没有pushdown就是不包含减去第四种。
然后转移的时候乘上系数就好了。
第一种:\(f_i=0,g_i=1\)
第二种:\(f_i=1,g_i=0\)
第三种:\(f_i=f_i,g_i=0\)
第四种:\(f_i=1-g_i,g_i=g_i\)
第五种:\(f_i=f_i,g_i=g_i\)
这样可以做到\(O(nk)\),恭喜你想了这么多只有30分。
\(k\)这么大自然是不能线性进复杂度的,考虑矩乘。
矩阵有三个数分别是\(f\),\(g\)和常数\(1\)。
然后随便矩乘就好了,时间复杂度\(O(27nlogk)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 200000
#define K 50
#define mod 998244353
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,k,Mid[N+5<<2],cnt=1;ll p1[N+5<<2],p2[N+5<<2],p3[N+5<<2],p4[N+5<<2],p5[N+5<<2],ToT,Invn;
I ll mpow(ll x,int y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}const ll inv2=mpow(2);
struct matrix{
ll A[3][3];matrix(){Me(A,0);}matrix operator *(const matrix &B)const{matrix C;re int i,j,h;for(h=0;h<3;h++) for(i=0;i<3;i++) for(j=0;j<3;j++) C.A[i][j]=(C.A[i][j]+A[i][h]*B.A[h][j])%mod;return C;}
}Ans,Bas;
I void Mpow(int k){Me(Ans.A,0);Ans.A[0][0]=Ans.A[1][1]=Ans.A[2][2]=1;while(k) k&1&&(Ans=Ans*Bas,0),k>>=1,Bas=Bas*Bas;}
I void build(int l,int r,int now){
l^r?(scanf("%d",&Mid[now])):(Mid[now]=l);p5[now]=(Invn*(1ll*l*(l-1)%mod+1ll*(n-r)*(n-r+1)%mod)%mod*inv2%mod-p4[now]+mod)%mod;p1[now]=(1-p2[now]-p3[now]-p4[now]-p5[now])%mod+mod;
Me(Bas.A,0);Bas.A[0][0]=(p3[now]+p5[now])%mod;Bas.A[1][0]=mod-p4[now];Bas.A[1][1]=(p4[now]+p5[now])%mod;Bas.A[2][0]=(p2[now]+p4[now])%mod;Bas.A[2][1]=p1[now];Bas.A[2][2]=1;
Mpow(k);ToT+=Ans.A[1][0]+Ans.A[2][0];/*printf("%lld %d %d %lld %lld %lld %lld\n",ToT%mod,l,r,Bas.A[1][0],Bas.A[2][0],p2[now],p4[now]);*/if(l==r) return;
++cnt;p2[cnt]=Invn*(r-Mid[now])%mod*l%mod;p3[cnt]=(p2[now]+p3[now])%mod;p4[cnt]=Invn*(n-Mid[now]+n-r+1)%mod*(r-Mid[now])%mod*inv2%mod;build(l,Mid[now],cnt);
++cnt;p2[cnt]=Invn*(Mid[now]-l+1)%mod*(n-r+1)%mod;p3[cnt]=(p2[now]+p3[now])%mod;p4[cnt]=Invn*(Mid[now]+l)%mod*(Mid[now]-l+1)%mod*inv2%mod;build(Mid[now]+1,r,cnt);
}
int main(){freopen("1.in","r",stdin);re int i;scanf("%d%d",&n,&k);Invn=mpow(1ll*n*(n+1)/2%mod);p2[1]=Invn;build(1,n,1);printf("%lld\n",ToT%mod);}