题解
真的都快忘了。
首先,我们考虑排序,求出一个神奇的排列方式,也就是dfn序。
那么答案必定是在dfn序里面一些连续的段连接起来。
然后我们就判断这玩意儿是否满足在a里面出现过。
于是现在分两步走:
第一步,假如现在有一个数字A,我们要判断其是否可以出现在a里面。
我们现在就有一种构造思路就是:从高位开始构造,假设现在构造到第i位,一直加个位之后,满足当前这位等于数字A的第i位后,继续构造第i-1位。
那么我们发现可以用一个神奇的DP来实现这个判断过程。
设(f_{i,p,x})表示当前做到第i位,最高位到第i位数字已经填完后最大的数字为p,个位为x开始,让第i位+1后个位变成(f_{i,p,x})。
这个就可以从低位开始转移到高位,每次让低位进位k次即可。注意这个p,不然会被搞崩心态。
然后再设一个(g_{i,j,p,x})表示的东东和上面类似,只是这个j表示的是让第i位进位到j。
转移的话就从j-1位进过去,利用f数值即可。
第二步,开始统计答案。
我们设(dp_{i,j,p,x})表示当前走到dfn序中的第i位,当前弄出来的数字是第j位,且当前位置放的是(d[dfn[i]]),最大值为p,各位从x开始的方案数。
我们发现,这个i是可以从(fa_i)到(i)这一段区间内转移过来的。
所以说,我们可以利用前缀和优化一下,时间复杂度就变成(O(n^2*k^2))
小细节巨多无比。
标程
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cctype>
using namespace std;
const long long mo=998244353;
const int maxn=501;
const int maxm=11;
int n,m,a[maxn],x[maxn],y[maxn],gs;
int f[maxn][maxm][maxm];
int g[maxn][maxm][maxm][maxm];
long long dp[maxn][maxn][maxm][maxm],sum[maxn][maxn][maxm][maxm];
int tot,nex[maxn*2],las[maxn*2],tov[maxn*2];
int dfn[maxn],wz[maxn],fa[maxn],dep;
int tot1,nex1[maxn*2],las1[maxn*2],tov1[maxn*2];
int son[maxn][maxn];
__attribute__((optimize("-O3")))
void qsort(int x,int l,int r)
{
int i=l;int j=r;
int m=son[x][(i+j)/2];
while (i<=j)
{
while (son[x][i]>m) i++;
while (son[x][j]<m) j--;
if (i<=j)
{
swap(son[x][i],son[x][j]);
i++;j--;
}
}
if (l<j) qsort(x,l,j);
if (r>i) qsort(x,i,r);
}
__attribute__((optimize("-O3")))
void insert(int x,int y)
{
tot++;
tov[tot]=y;
nex[tot]=las[x];
las[x]=tot;
}
__attribute__((optimize("-O3")))
void insert1(int x,int y)
{
tot1++;
tov1[tot1]=y;
nex1[tot1]=las1[x];
las1[x]=tot1;
}
__attribute__((optimize("-O3")))
void dfs(int x,int ff)
{
gs++;
dfn[x]=gs;
wz[gs]=x;
for (int i=las1[x];i>0;i=nex1[i])
{
if (tov1[i]!=ff)
{
fa[tov1[i]]=x;
dfs(tov1[i],x);
}
}
}
__attribute__((optimize("-O3")))
void dfssort(int x,int ff)
{
for (int i=las[x];i>0;i=nex[i])
{
if (tov[i]!=ff)
{
son[x][0]++;
son[x][son[x][0]]=tov[i];
dfssort(tov[i],x);
}
}
qsort(x,1,son[x][0]);
for (int i=1;i<=son[x][0];i++)
{
insert1(x,son[x][i]);
insert1(son[x][i],x);
}
}
__attribute__((optimize("-O3")))
int main()
{
// freopen("data.in","r",stdin);
freopen("buried.in","r",stdin);
freopen("buried.out","w",stdout);
scanf("%d%d",&n,&m);
for (register int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for (register int i=1;i<n;i++)
{
scanf("%d%d",&x[i],&y[i]);
insert(x[i],y[i]);
insert(y[i],x[i]);
}
dfssort(1,0);
dfs(1,0);
for (register int i=1;i<=n;i++)
{
for (register int p=0;p<m;p++)
{
for (register int x=0;x<m;x++)
{
f[i][p][x]=-1;
for (register int a=0;a<m;a++)
{
g[i][p][a][x]=-1;
}
}
}
}
for (register int i=0;i<m;i++)
{
for (register int x=0;x<m;x++)
{
if (i>0 || (i==0 && x>0))
{
register int j=x;
while (j<m)
{
g[1][i][j][x]=j;
j=j+max(j,i);
}
f[1][i][x]=j%m;
g[2][i][1][x]=j%m;
}
}
}
for (register int i=0;i<m;i++)
{
for (register int x=0;x<m;x++)
{
g[2][i][0][x]=x;
if (i>0 || (i==0 && x>0))
{
register int j=f[1][i][x];
for (register int cs=2;cs<m;cs++)
{
g[2][i][cs][x]=f[1][max(i,cs-1)][j];
j=f[1][max(i,cs-1)][j];
}
}
}
}
for (register int i=2;i<=n;i++)
{
for (register int p=0;p<m;p++)
{
for (register int x=0;x<m;x++)
{
if (p>0 || (p==0 && x>0))
{
register int op=x;
g[i][p][0][x]=x;
for (register int j=0;j<m;j++)
{
op=f[i-1][max(p,j)][op];
if (j<m-1) g[i][p][j+1][x]=op;
}
f[i][p][x]=op;
}
}
}
}
for (register int i=3;i<=n;i++)
{
for (register int p=0;p<m;p++)
{
for (register int x=0;x<m;x++)
{
if (p>0 || (p==0 && x>0))
{
register int op=f[i-2][m-1][g[i-1][p][m-1][x]];
g[i][p][1][x]=op;
}
}
}
}
for (register int i=3;i<=n;i++)
{
for (register int p=0;p<m;p++)
{
for (register int x=0;x<m;x++)
{
g[i][p][0][x]=x;
if (p>0 || (p==0 && x>0))
{
register int j=g[i][p][1][x];
for (register int cs=2;cs<m;cs++)
{
g[i][p][cs][x]=f[i-1][max(p,cs-1)][j];
j=f[i-1][max(p,cs-1)][j];
}
}
}
}
}
for (register int i=1;i<=n;i++)
{
dp[1][i][a[1]][g[i][0][a[1]][1]]=1;
sum[1][i][a[1]][g[i][0][a[1]][1]]=1;
}
for (register int i=2;i<=n;i++)
{
for (register int p=0;p<m;p++)
{
for (register int x=0;x<m;x++)
{
for (register int w=1;w<=n-i+1;w++)
{
if (g[w][p][a[wz[i]]][x]>=0)
{
dp[i][w][max(p,a[wz[i]])][g[w][p][a[wz[i]]][x]]=
(dp[i][w][max(p,a[wz[i]])][g[w][p][a[wz[i]]][x]]+sum[i-1][w+1][p][x]-sum[dfn[fa[wz[i]]]-1][w+1][p][x]+mo)%mo;
}
}
}
}
memcpy(sum[i],sum[i-1],sizeof(sum[i-1]));
for (register int w=1;w<=n-i+1;w++)
{
for (register int x=0;x<m;x++)
{
for (register int p=0;p<m;p++)
{
// if (g[w][p][a[wz[i]]][x]>=0)
{
sum[i][w][p][x]=
(sum[i][w][p][x]+dp[i][w][p][x])%mo;
}
}
}
}
}
long long ans=0;
for (register int i=1;i<=n;i++)
{
for (register int j=a[wz[i]];j<m;j++)
{
ans=(ans+dp[i][1][j][a[wz[i]]])%mo;
}
}
printf("%lld
",ans);
}