换根 DP。
本蒟蒻最初没想到换根,把自己写自闭了...
定义 \(f_u\) 为子树 \(u\) 中的每个结点走到 \(u\) 的贡献和,\(l_u\) 为大于 \(a_u\) 的最小的 \(10\) 的幂次方数,\(sum_u\) 为 \(\sum\limits_{v\in son(u)}{f_v}\)。
转移方程为:\(f_u=l_u\cdot\sum\limits_{v\in son(u)}{f_v}+siz_u\cdot a_u\)。
再定义 \(g_u\) 为除去子树 \(u\) 其他的所有点到 \(fa_u\) 的贡献和。
转移方程为:\(g_v=(g_u+sum_u-f_v)\cdot l_u+(n-siz_v)\cdot a_u\)。
然后答案加上 \((g_v+sum_v)\cdot l_v+n\cdot a_v\)。
复杂度 \(O(n)\)。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5,mod=998244353;
ll n,a[N],f[N],g[N],siz[N],sum[N],ans;
vector<int>adj[N];
ll get(ll x){
if(x==0)return 10;
ll res=1;
while(x){res*=10;x/=10;}
return res;
}
void dfs(int u,int lst){
siz[u]=1;
ll t=get(a[u]);f[u]=a[u];
for(int i=0;i<adj[u].size();++i){
int v=adj[u][i];if(v==lst)continue;
dfs(v,u);siz[u]+=siz[v];f[u]=(f[u]+f[v]*t+siz[v]*a[u])%mod;sum[u]=(sum[u]+f[v])%mod;
}
}
void dfs2(int u,int lst){
ll tu=get(a[u]);
for(int i=0;i<adj[u].size();++i){
ll v=adj[u][i],tv=get(a[v]);if(v==lst)continue;
g[v]=(g[u]+(sum[u]-f[v]+mod)%mod)%mod*tu+(n-siz[v])*a[u];g[v]%=mod;
ans=(ans+(g[v]+sum[v])*tv+n*a[v])%mod;
dfs2(v,u);
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n;for(int i=1;i<=n;++i)cin>>a[i];
for(int u=2;u<=n;++u){
int v;cin>>v;
adj[u].push_back(v);adj[v].push_back(u);
}
dfs(1,0);ans+=f[1];dfs2(1,0);
cout<<ans<<endl;
return 0;
}
标签:10,P9437,题解,sum,int,XYGOI,siz,cdot,ll
From: https://www.cnblogs.com/HQJ2007/p/17561568.html