【学习笔记】[AGC063E] Child to Parent

提供一个多项式做法。

分别设 f u , i , g u , i f_{u,i},g_{u,i} fu,i,gu,i表示以 u u u为根时, a u = i a_u=i au=i和 a u ≥ i a_u\ge i au≥i的方案数,合并子树 v v v时,转移如下:

f u , i = ∑ f u , i − k r × g v . k f_{u,i}=\sum f_{u,i-kr}\times g_{v.k} fu,i=∑fu,i−kr×gv.k

初值为 f u , a u = 1 f_{u,a_u}=1 fu,au=1。

注意到 DP 的值域很大,通常情况下我们可以考虑用拉格朗日插值法来处理,但是实际上只要满足信息封闭也是可以转移的。我们不妨将其转化成多项式的形式,从而来观察需要记录哪些信息。

设:
F u ( x ) = ∑ f u , i x i G u ( x ) = ∑ g u , i x i F_u(x)=\sum f_{u,i}x^i\\G_u(x)=\sum g_{u,i}x^i Fu(x)=∑fu,ixiGu(x)=∑gu,ixi

转移大致分为以下几步:

F u ( x ) ← ∏ G v ( x ) F u ( x ) ← x a i F u ( x r ) G u ( x ) ← F u ( x ) + F u ( 1 ) − F u ( x ) 1 − x F_u(x)\gets \prod G_v(x)\\F_u(x)\gets x^{a_i}F_u(x^r)\\ G_u(x)\gets F_u(x)+\frac{F_u(1)-F_u(x)}{1-x} Fu(x)←∏Gv(x)Fu(x)←xaiFu(xr)Gu(x)←Fu(x)+1−xFu(1)−Fu(x)

其中最后一个式子是在求后缀和,之所以不能写成 1 1 − x − 1 \frac{1}{1-x^{-1}} 1−x−11的原因是生成函数不能有次数 < 0 <0 <0的项。

现在问题在于,要求出 F u ( 1 ) F_u(1) Fu(1)就必须维护各项系数,显然次数太高就寄了。考虑一步非常巧妙的转化:我们设 G u ′ ( x ) = G u ( x + 1 ) , F u ′ ( x ) = F u ( x + 1 ) G'_u(x)=G_u(x+1),F'_u(x)=F_u(x+1) Gu′(x)=Gu(x+1),Fu′(x)=Fu(x+1),则 F u ′ ( 0 ) = F u ( 1 ) F'_u(0)=F_u(1) Fu′(0)=Fu(1),而 F u ′ ( 0 ) F'_u(0) Fu′(0)其实就是常数项,又因为要求的答案也是常数项,这样我们只用算次数较低的项,信息就封闭了。

新的转移大致为:

F u ′ ( x ) ← ∏ G v ′ ( x ) F'_u(x)\gets \prod G'_v(x)\\ Fu′(x)←∏Gv′(x)

这是因为

F u ′ ( x ) = F u ( x + 1 ) = ∏ G v ( x + 1 ) = ∏ G v ′ ( x ) F'_u(x)=F_u(x+1)=\prod G_v(x+1)=\prod G'_v(x) Fu′(x)=Fu(x+1)=∏Gv(x+1)=∏Gv′(x)

F u ′ ( x ) ← ( x + 1 ) a i F u ′ ( ( x + 1 ) r − 1 ) F_u'(x)\gets (x+1)^{a_i}F_u'((x+1)^r-1) Fu′(x)←(x+1)aiFu′((x+1)r−1)

这是因为

F u ′ ( x ) = F u ( x + 1 ) = ( x + 1 ) a i F u ( ( x + 1 ) r ) = ( x + 1 ) a i F u ′ ( ( x + 1 ) r − 1 ) F'_u(x)=F_u(x+1)=(x+1)^{a_i}F_u((x+1)^r)=(x+1)^{a_i}F_u'((x+1)^r-1) Fu′(x)=Fu(x+1)=(x+1)aiFu((x+1)r)=(x+1)aiFu′((x+1)r−1)

G u ′ ( x ) = F u ′ ( x ) + F u ′ ( 0 ) − F u ′ ( x ) − x G'_u(x)=F'_u(x)+\frac{F'_u(0)-F'_u(x)}{-x} Gu′(x)=Fu′(x)+−xFu′(0)−Fu′(x)

如果我们只保留前 k k k项,那么因为要除以 x x x,所以每次转移完后最后一项都会损失掉。但是因为答案是第一项的值,所以我们对于每个节点保留 d e p u dep_u depu项即可。

复杂度 O ( n 3 ) O(n^3) O(n3)。

麻了,好像和官方题解长得一样。

cpp 复制代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int mod=998244353;
int n,fa[305],dep[305];
ll r,fac[305],inv[305],ifac[305],to[305][305],f[305][305],g[305][305],a[305],res;
vector<int>G[305];
ll fpow(ll x,ll y=mod-2){
    ll z(1);
    for(;y;y>>=1){
        if(y&1)z=z*x%mod;
        x=x*x%mod;
    }return z;
}
ll binom(int x,int y){
    if(x<0||y<0||x<y)return 0;
    return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
void init(int n){
    fac[0]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;
    inv[n]=fpow(fac[n]);for(int i=n;i>=1;i--)inv[i-1]=inv[i]*i%mod;
    ifac[1]=1;for(int i=2;i<=n;i++)ifac[i]=mod-ifac[mod%i]*(mod/i)%mod;
}
void dfs(int u){
    f[u][0]=1;
    for(auto v:G[u]){
        dep[v]=dep[u]+1,dfs(v);
        memset(f[0],0,sizeof f[0]);
        for(int i=0;i<=dep[v];i++)for(int j=0;i+j<=dep[v];j++)(f[0][i+j]+=f[u][i]*g[v][j])%=mod;
        memcpy(f[u],f[0],sizeof f[0]);
    }
    memset(f[0],0,sizeof f[0]);
    for(int i=0;i<=dep[u]+1;i++)for(int j=0;j<=dep[u]+1;j++)(f[0][j]+=f[u][i]*to[i][j])%=mod;
    memset(f[u],0,sizeof f[u]);
    ll mul=1;
    for(int i=0;i<=dep[u]+1;i++){
        for(int j=0;i+j<=dep[u]+1;j++)(f[u][i+j]+=mul*f[0][j])%=mod;
        mul=mul*(a[u]-i)%mod*ifac[i+1]%mod;
    }
    for(int i=0;i<=dep[u];i++)g[u][i]=(f[u][i]+f[u][i+1])%mod;
}
signed main(){
    //freopen("data.in","r",stdin);
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n;for(int i=2;i<=n;i++)cin>>fa[i],G[fa[i]].pb(i);
    cin>>r;init(n);
    to[0][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=i;j++){
            ll mul=1;int sgn=(i-j&1)?-1:1;
            for(int k=0;k<=n;k++){
                (to[i][k]+=sgn*binom(i,j)*mul)%=mod;
                mul=mul*((j*r-k)%mod)%mod*ifac[k+1]%mod;
            }
        }
    }
    for(int i=1;i<=n;i++)cin>>a[i];
    dfs(1);
    cout<<(f[1][0]+mod)%mod;
}
相关推荐
-Springer-10 分钟前
STM32 学习 —— 个人学习笔记9-3(FlyMcu 串口下载)
笔记·stm32·学习
weixin_458872611 小时前
东华复试OJ每日3题打卡·复盘103~105
学习
SuniaWang1 小时前
《Spring AI + 大模型全栈实战》学习手册系列 ·专题三:《Embedding 模型选型指南:从 MMTEB 排名到实际应用》
人工智能·学习·spring
问道飞鱼1 小时前
【Tauri框架学习】Windows 11 环境下 Tauri 开发环境安装与问题解决手册
windows·学习·tauri·开发环境
中屹指纹浏览器1 小时前
2026指纹浏览器与代理IP协同安全体系构建——从特征匹配到行为风控的全链路防护
经验分享·笔记
لا معنى له2 小时前
什么是Active Inference(主动推理)? ——学习笔记
笔记·学习
JicasdC123asd2 小时前
并行双分支瓶颈架构改进YOLOv26异构卷积核协同特征提取与残差学习双重突破
学习·yolo·架构
zhouping@2 小时前
JAVA学习笔记day06
java·笔记·学习
Jack.Jia2 小时前
GPS原理笔记三——GPS卫星轨道理论和计算
笔记
庞轩px2 小时前
内存区域的演进与直接内存——JVM性能优化的权衡艺术
java·jvm·笔记·性能优化