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
}

posted @ 2026-08-13 11:17  MCYYDS  阅读(12)  评论(0)    收藏  举报