AGC068D Sum of Hash of Lexmin 题解
题目链接:AGC068D - Sum of Hash of Lexmin
首先有一个结论,如果可以交换一对数使得排列字典序变小,那么就不是好排列,否则是好排列,具体可以反证。然后我们对这种情况容斥,即存在 $ u, v $ 满足 $ u $ 是 $ v $ 的祖先且 $ v $ 在排列中恰好是 $ u $ 的前一个,我们在这种情况下视为有一条有向边 $ u\to v $,于是所有的边后尘了若干条不相较的链,dp 即可,将 $ B $ 加入到 dp 过程中计算,状态大致是 $ f_{a,b} $ 代表一条路径覆盖,总共长度为 $ a+b $,在 $ a $ 和 $ a+1 $ 中分解,$ g_{a,b} $ 则代表当前总共有 $ a+b+1 $ 条路径覆盖,当前选中的路径前面有 $ a $ 条路径,后面有 $ b $ 条,然后正常 dp 转移即可。
代码:
#include<bits/stdc++.h>
#define time(null) chrono::steady_clock::now().time_since_epoch().count()
#define int long long
#define uint unsigned long long
#define debug() cout<<"come here\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define pb push_back
#define Code return
#define by 0
#define MCYYDS ;
using namespace std;
int qpow(int a,int b,int p=INF){int ret=1;while(b){if(b&1)ret=(ret*a)%p;a=(a*a)%p;b>>=1;}return ret;}
inline int read(){int ret=0,f=1;char ch=getchar();while(ch<'0'||ch>'9')f=(ch=='-'?-1:f),ch=getchar();while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();return ret*f;}
inline void write(int x){if(x<0){putchar('-');write(-x);return ;}if(x>9)write(x/10);putchar((char)(x%10+48));}
inline void writech(int x,char ch){write(x);putchar(ch);}
const int mod=998244353;
int n,B,c[105][105];
vector<int> e[105];
struct node{
int s;
vector<vector<int> > f,g;
};
node dfs(int u)
{
node cur;
cur.s=0;
cur.f={{1}};
cur.g={{0}};
for(auto v:e[u])
{
node t=dfs(v);
int s=cur.s,ts=t.s;
vector<vector<int> > nf(s+ts+1,vector<int>(s+ts+1)),ng(s+ts+1,vector<int>(s+ts+1));
for(int a=0;a<=s;a++)
{
for(int b=0;a+b<=s;b++)
{
int fv=cur.f[a][b],gv=cur.g[a][b];
if(!fv&&!gv)continue;
for(int x=0;x<=ts;x++)
{
for(int y=0;x+y<=ts;y++)
{
int tfv=t.f[x][y],tgv=t.g[x][y];
if(!tfv&&!tgv)continue;
nf[a+x][b+y]=(nf[a+x][b+y]+fv*tfv%mod*c[a+x][a]%mod*c[b+y][b]%mod)%mod;
ng[a+x][b+y]=(ng[a+x][b+y]+(gv*tfv%mod+fv*tgv%mod)%mod*c[a+x][a]%mod*c[b+y][b]%mod)%mod;
}
}
}
}
cur.s=s+ts;
swap(cur.f,nf);
swap(cur.g,ng);
}
int s=cur.s;
vector<vector<int> > nf(s+2,vector<int>(s+2)),ng(s+2,vector<int>(s+2));
for(int x=0;x<=s;x++)
{
for(int y=0;x+y<=s;y++)
{
int f=cur.f[x][y],g=cur.g[x][y];
nf[x+1][y]=(nf[x+1][y]+f*(x+1)%mod*B%mod)%mod;
nf[x][y+1]=(nf[x][y+1]+f*(y+1)%mod)%mod;
nf[x][y]=(nf[x][y]-f*((x*B+y)%mod)%mod+mod)%mod;
ng[x+1][y]=(ng[x+1][y]+g*(x+1)%mod*B%mod)%mod;
ng[x][y+1]=(ng[x][y+1]+g*(y+1)%mod)%mod;
ng[x][y]=(ng[x][y]-g*((x*B+y+1)%mod)%mod+mod)%mod;
ng[x][y]=(ng[x][y]+u*f%mod)%mod;
if(x+y+1<=s)ng[x][y]=(ng[x][y]-u*cur.f[x+1][y]%mod+mod)%mod;
}
}
cur.s=s+1;
swap(cur.f,nf);
swap(cur.g,ng);
return cur;
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
for(int i=0;i<=100;i++)
{
c[i][0]=c[i][i]=1;
for(int j=1;j<i;j++)
{
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
n=read(),B=read();
for(int i=2;i<=n;i++)
{
int fa=read();
e[fa].pb(i);
}
node ans=dfs(1);
int sum=0;
for(int i=0;i<=n;i++)
{
for(int j=0;i+j<=n;j++)
{
sum=(sum+ans.g[i][j])%mod;
}
}
writech(sum,'\n');
Code by MCYYDS
}

浙公网安备 33010602011771号