loj#3312. 「ZJOI2020」传统艺能
题目描述
题解
签到题,比T3不知道阳间到哪里去了
分开计算每个区间的答案,一次修改对于一个区间有5种情况:
①没有任何影响,即在父亲区间外
②使当前区间直接覆盖
③使当前区间及祖先区间清空
④覆盖祖先区间
⑤把祖先区间的标记传到当前区间
分别算出五种情况的概率(相加要为1),设dpf[i][0/1/2]表示当前及祖先区间无标记,祖先区间有标记,当前区间有标记,矩乘加速
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%998244353
#define mod 998244353
#define Mod 998244351
#define ll long long
//#define file
using namespace std;
struct mat{ll a[3][3];void clear() {memset(a,0,sizeof(a));}} a,b,aI;
mat mul(mat &a,mat b)
{
static mat c;
int i,j,k,l;
fo(i,0,2)
{
fo(j,0,2)
{
c.a[i][j]=0;
fo(k,0,2)
add(c.a[i][j],a.a[i][k]*b.a[k][j]);
}
}
a=c;
}
int m,i,j,k,l;
ll n,ans,N,Ny;
set<int> st;
set<int> :: iterator I,J;
ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
void js(ll fx,ll fy,ll x,ll y)
{
ll s0=((fx-1)*fx/2+(n-fy)*(n-fy+1)/2)%mod,s1=((x-fx)*(n-y+1)+(fy-y)*x)%mod,s2=((y-x+1)*n-(y-x+1)*(y-x+2)/2+(y-x+1)-(n-y+1)-x+1)%mod,
s3=(fx*(n-fy+1))%mod,s4=((x-fx)*(fx-1)+(x-fx)*(x-fx+1)/2+(fy-y)*(n-fy)+(fy-y)*(fy-y+1)/2)%mod;
s0=s0*Ny%mod;s1=s1*Ny%mod;s2=s2*Ny%mod;s3=s3*Ny%mod;s4=s4*Ny%mod;
int i;
i=m;a=aI;b.clear();
add(b.a[0][0],s0),add(b.a[1][1],s0),add(b.a[2][2],s0);
add(b.a[0][2],s1),add(b.a[1][2],s1),add(b.a[2][2],s1);
add(b.a[0][0],s2),add(b.a[1][0],s2),add(b.a[2][0],s2);
add(b.a[0][1],s3),add(b.a[1][1],s3),add(b.a[2][2],s3);
add(b.a[0][0],s4),add(b.a[1][2],s4),add(b.a[2][2],s4);
while (i)
{
if (i&1) mul(a,b);
mul(b,b);i>>=1;
}
add(ans,a.a[0][2]);
}
int main()
{
#ifdef file
freopen("loj3312.in","r",stdin);
#endif
scanf("%lld%d",&n,&m);st.insert(1);st.insert(n+1);N=(n*(n+1)/2)%mod;Ny=qpower(N,Mod);aI.a[0][0]=aI.a[1][1]=aI.a[2][2]=1;
ans=Ny;
fo(i,1,n-1)
{
scanf("%d",&j);
J=st.upper_bound(j);I=J;--I;
js(*I,(*J)-1,*I,j);
js(*I,(*J)-1,j+1,(*J)-1);
st.insert(j+1);
}
printf("%lld\n",(ans+mod)%mod);
fclose(stdin);
fclose(stdout);
return 0;
}