「国家集训队」 Crash 的文明世界

提供一种不需要脑子的方法。

其实是看洛谷讨论版看出来的(

(但是全网也就这一篇这个方法的题解了)

首先这是一个关于树上路径的问题,我们可以无脑上点分治。

考虑当以 \(root\) 为根时,如何计算经过 \(root\) 的路径对某一个点的贡献。

若现在我们要找经过 \(root\) 的路径中长度为 \(d\) 且路径的一端为 \(u\)。

则这一部分的贡献为 \(v_{d}cnt_{d-h_u}\),其中 \(v_d=d^k\),\(h_u\) 表示点 \(u\) 的深度,\(cnt_i\) 表示深度为 \(i\) 的节点个数。

当然这里会有一种不合法的情况,就是找到的路径两端点在 \(root\) 的同一棵子树中。这可以用点分治惯用的容斥解决。

以 \(root\) 为根时,路径对点 \(u\) 的贡献为(事实上对深度为 \(h_u\) 的节点贡献是相同的)

\[\sum_{d=h_u}^{maxdeep+h_u}v_dcnt_{d-h_u}\\
\]

为了处理起来更加方便,我们增加一些无用的部分

于是有

\[\sum_{d=0}^{2\times maxdeep}v_dcnt_{d-h_u}\\
\]

令 \(n=2\times maxdeep\)。

\[\sum_{d=0}^{n}v_dcnt_{d-h_u}\\
\]

按照套路,将 \(cnt\) 数组翻转一下

\[\sum_{d=0}^{n}v_dcnt_{n-d+h_u}\\
\]

\[Ans_{n+h_u}=\sum_{d=0}^{n}v_dcnt_{n-d+h_u}\\
\]

这是一个卷积的形式,直接 \(\texttt{FFT/NTT}\) 即可。

所以总时间复杂度为 \(O(n\log_2^2n)\)。

(所以为啥不把这题的 k 开到和 n 同级呢)

下面讲讲常数优化:

  • 预处理原根、单位根必不可少。
  • 能不取模尽量别取模。
  • 由于这也是在分治的过程中进行 \(\texttt{FFT}\) 的计算,所以当规模较小时暴力会更快。

另外值得注意的是,由于本题的模数不是一个 \(\texttt{NTT}\) 模数,而中间过程中的结果最大可能为 \(10006^2\) ,所以我们可能得选择恰当的 \(\texttt{NTT}\) 模数。

这样的话结果就一定不会有问题。

这个题就这样非常套路地被我们解决了。

贴一个很丑的代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
const int p=1e4+7;
const int P=1004535809;
int n,k;
struct edge{
int to,nex;
}e[maxn<<1];
int head[maxn],tot;
int siz[maxn],dp[maxn],vis[maxn],rt;
int w[maxn],cnt[maxn],ans[maxn];
int f[maxn],g[maxn],rev[maxn],len=1;
void add(int a,int b){
e[++tot]=(edge){b,head[a]};
head[a]=tot;
}
int ksm(int a,int b,int p){
int ans=1;
while(b){
if(b&1) ans=1ll*ans*a%p;
b>>=1,a=1ll*a*a%p;
}
return ans;
}
vector<int> W[20];
void INIT(){
for(int i=1,num=0;num<=17;++num,i<<=1){
int w=ksm(3,(P-1)/(i<<1),P),tmp=1;
for(int k=0;k<i;++k)
W[num].emplace_back(tmp),tmp=1ll*tmp*w%P;
}
}
void NTT(int *f){
for(int i=0;i<len;++i)
if(i<rev[i]) swap(f[i],f[rev[i]]);
for(int i=1,num=0;i<len;i<<=1,++num){
for(int j=0;j<len;j+=(i<<1)){
for(int k=0;k<i;++k){
int x=f[j|k],y=1ll*W[num][k]*f[i|j|k]%P;
f[j|k]=x+y>P?x+y-P:x+y;
f[i|j|k]=x-y<0?x-y+P:x-y;
}
}
}
}
void init(int x){
len=1;
while(len<=x) len<<=1;
f[0]=g[0]=0;
for(int i=1;i<len;++i)
rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
memset(f,0,sizeof (int)*len);
memset(g,0,sizeof (int)*len);
}
void getroot(int u,int f,int sum){
siz[u]=1,dp[u]=0;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(v==f||vis[v]) continue;
getroot(v,u,sum);
siz[u]+=siz[v];
dp[u]=max(siz[v],dp[u]);
}
dp[u]=max(dp[u],sum-siz[u]);
if(dp[u]<dp[rt]) rt=u;
}
void clear(int u,int f,int dis,int &mx){
mx=max(mx,dis);
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(v==f||vis[v]) continue;
clear(v,u,dis+1,mx);
}
}
void getdis(int u,int f,int dis){
++cnt[dis];
if(cnt[dis]>=p) cnt[dis]-=p;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(v==f||vis[v]) continue;
getdis(v,u,dis+1);
}
}
int owo[251];
void mul(int *a,int *b,int n){
if(n<=100){
memset(owo,0,sizeof (int)*(2*n+1));
for(int i=0;i<=n;++i)
for(int j=0;j<=n;++j)
owo[i+j]=owo[i+j]+1ll*a[i]*b[j]%P>P?owo[i+j]+1ll*a[i]*b[j]%P-P:owo[i+j]+1ll*a[i]*b[j]%P;
for(int i=0;i<=2*n;++i) a[i]=owo[i];
return ;
}
memcpy(f,a,sizeof (int)*(n+1));
memcpy(g,b,sizeof (int)*(n+1));
NTT(f),NTT(g);
for(int i=0;i<len;++i) f[i]=1ll*f[i]*g[i]%P;
NTT(f);
reverse(f+1,f+len);
int inv=ksm(len,P-2,P);
for(int i=0;i<=2*n;++i) a[i]=1ll*f[i]*inv%P;
}
void dfs(int u,int f,int dis,int opt){
ans[u]+=opt*cnt[dis];
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(v==f||vis[v]) continue;
dfs(v,u,dis+1,opt);
}
}
void calc(int u,int dis,int opt){
int n=0;
clear(u,0,dis,n);n*=2;
memset(cnt,0,sizeof (int)*(n+1));
getdis(u,0,dis);
reverse(cnt,cnt+n+1);
init(2*n);
mul(cnt,w,n);
for(int i=0;i<=n;++i) cnt[i]=cnt[i+n];
dfs(u,0,dis,opt);
}
void solve(int u){
vis[u]=1;
calc(u,0,1);
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(vis[v]) continue;
calc(v,1,-1);
rt=0;
getroot(v,0,siz[v]);
solve(rt);
}
}
int main(){
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>k;
INIT();
for(int i=1;i<n;++i){
int a,b;cin>>a>>b;
add(a,b),add(b,a);
}
for(int i=0;i<n;++i) w[i]=ksm(i,k,p);
dp[0]=(1<<30);
getroot(1,0,n);
solve(rt);
for(int i=1;i<=n;++i) cout<<ans[i]%p<<'\n';
}

P4827「国家集训队」 Crash 的文明世界的更多相关文章

  1. 「国家集训队」Crash的数字表格

    题目描述 求(对 \(20101009\) 取模,\(n,m\le10^7\) ) \[\sum_{i=1}^n\sum_{j=1}^m\operatorname{lcm}(i,j)\] 大体思路 推 ...

  2. 「国家集训队」middle

    「国家集训队」middle 传送门 按照中位数题的套路,二分答案 \(mid\),序列中 \(\ge mid\) 记为 \(1\),\(< mid\) 的记为 \(-1\) 然后只要存在一个区间 ...

  3. 「国家集训队」小Z的袜子

    「国家集训队」小Z的袜子 传送门 莫队板子题. 注意计算答案的时候,由于分子分母都要除以2,所以可以直接约掉,这样在开桶算的时候也方便一些. 参考代码: #include <algorithm& ...

  4. 「洛谷1903」「BZOJ2120」「国家集训队」数颜色【带修莫队,树套树】

    题目链接 [BZOJ传送门] [洛谷传送门] 题目大意 单点修改,区间查询有多少种数字. 解法1--树套树 可以直接暴力树套树,我比较懒,不想写. 稍微口胡一下,可以直接来一个树状数组套主席树,也就是 ...

  5. Solution -「国家集训队」「洛谷 P2619」Tree I

    \(\mathcal{Description}\)   Link.   给一个 \(n\) 个点 \(m\) 条边的带权无向图,边有权值和黑白颜色,求恰选出 \(K\) 条白边构成的最小生成树.    ...

  6. Solution -「国家集训队」「洛谷 P2839」Middle

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_n\}\),\(q\) 组询问,给定 \(a<b<c<d\),求 \(l\le[a,b] ...

  7. Solution -「国家集训队」「洛谷 P4451」整数的 lqp 拆分

    \(\mathcal{Description}\)   Link.   求 \[\sum_{m>0\\a_{1..m}>0\\a_1+\cdots+a_m=n}\prod_{i=1}^mf ...

  8. [国家集训队] Crash 的文明世界(第二类斯特林数)

    题目 [国家集训队] Crash 的文明世界 前置 斯特林数\(\Longrightarrow\)斯特林数及反演总结 做法 \[\begin{aligned} ans_x&=\sum\limi ...

  9. 【BZOJ2159】Crash的文明世界

    [2011集训贾志鹏]Crash的文明世界 Description Crash小朋友最近迷上了一款游戏--文明5(Civilization V).在这个游戏中,玩家可以建立和发展自己的国家,通过外交和 ...

随机推荐

  1. Step By Step(Lua元表与元方法)

    Step By Step(Lua元表与元方法) Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表 ...

  2. 如何写新的Python OP

    如何写新的Python OP Paddle 通过 py_func 接口支持在Python端自定义OP. py_func的设计原理在于Paddle中的Tensor可以与numpy数组可以方便的互相转换, ...

  3. 腾讯 angel 3.0:高效处理模型

    腾讯 angel 3.0:高效处理模型 紧跟华为宣布新的 AI 框架开源的消息,腾讯又带来了全新的全栈机器学习平台 angel3.0.新版本功能特性覆盖了机器学习的各个阶段,包括:特征工程.模型训练. ...

  4. CodeGen API分析

    CodeGen API分析 作为使用命令行界面的替代方法,开发人员可以使用核心CodeGen环境编写自定义工具或实用程序来生成代码,从而将CodeGen更紧密地集成到开发环境中. 为了实现这一点,Co ...

  5. dataguard日志损坏处理

    ===== 问题 ===== 日志损坏无法应用日志(开启MRP应用系统会因无法应用日志而关闭) Completed: ALTER DATABASE RECOVER MANAGED STANDBY DA ...

  6. .NET平台系列23:.NET Core/.NET5/.NET6 和 .NET Framework 的选择建议

    系列目录     [已更新最新开发文章,点击查看详细] 有两种支持的 .NET 实现可用于生成服务器端应用: .NET Framework .NET Core/5+,包括 .NET Core..NET ...

  7. 12:media配置以及后端指定资源暴露

    django需要用到的静态文件默认都是放在static目录下 而针对后期用户上传的静态文件也应该统一存储 # media配置:规定用户上传的静态文件存储位置 MEDIA_ROOT = os.path. ...

  8. 身为一枚优秀的程序员必备的基于Redis的分布式锁和Redlock算法

    1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手锏功能,是基于Redi ...

  9. Air722UG_模块硬件设计手册_V1.1

    下载PDF版本: Air722UG_模块硬件设计手册_V1.1.pdf @ 目录 1. 绪论 2.综述 2.1 型号信息 2.2 主要性能 2.3 功能框图 3.应用接口 3.1 管脚描述 3.2 工 ...

  10. MindSpore自定义模型损失函数

    技术背景 损失函数是机器学习中直接决定训练结果好坏的一个模块,该函数用于定义计算出来的结果或者是神经网络给出的推测结论与正确结果的偏差程度,偏差的越多,就表明对应的参数越差.而损失函数的另一个重要性在 ...