该思博的时候就思博到底,套路的时候不能再套路的一道题

首先我们将联通块的大小平方和进行转化,发现它就等价于连通点对数,而这个可以转化为连接两点的边数(距离)和

所以我们考虑第\(i\)天时,一个点对\((x,y)\)能产生贡献,当且仅当连接它们的边一条都没断,故贡献为:

\[\frac{(n-1-\operatorname{dis}(x,y))^{\underline i}}{(n-1)^{\underline i}}\]

因此我们发现这个东西对于所有距离相同的点对是一样的,因此我们可以直接统计出所有的距离为\(i(i\in[0,n-1])\)的点对数\(num_i\)

然后考虑对于一天\(i\)枚举距离为\(d\)的点对,则:

\[ans_i=\sum_{d=0}^{n-1}\frac{(n-d-1)!\times(n-i-1)!\times num_d}{(n-d-i-1)!\times(n-1)!}\]

显然是一个卷积的形式,我们令\(A(x)=(n-i-1)!\times num_i,B(x)=\frac{1}{i!}\),卷积之后乘回不变项然后反转即可

那么剩下还有两个问题,距离为\(i\)的点对数怎么求?

首先一眼点分治,然后有一个很naive的想法就是遍历每颗子树信息后暴力FFT合并

但这样遇到菊花图就直接GG了,因此我们可以容斥一下

每次以分治中心为根找出所有长度的路径条数,然后卷积平方后减去重复在同一子树内的部分即可,计算方法和之前一致

最后一个问题,模数不是NTT模数毒瘤出题人,难不成我们写三模NTT

然而发现之前FFT已经写好了,因此我们直接拆系数做就好了

PS:本人太弱不会MTT,因此写了最暴力的4次DFT,4次IDFT的大常数版本,复杂度就当作两只\(\log\)来看吧

最后跑了1.36s,注意开long longlong double

CODE

#include<cstdio>
#include<cctype>
#include<iostream>
#include<cmath>
#define int LL
#define RI register int
#define CI const int&
#define Tp template <typename T>
#define CC const Complex&
using namespace std;
typedef long long LL;
const int N=200005,INF=1e9,mod=1e9+7;
const long double pi=acos(-1);
class FileInputOutput
{private:static const int S=1<<21;#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)#define pc(ch) (Ftop!=Fend?*Ftop++=ch:(fwrite(Fout,1,S,stdout),*(Ftop=Fout)++=ch))char Fin[S],Fout[S],*A,*B,*Ftop,*Fend; int pt[15];public:inline FileInputOutput() { Ftop=Fout; Fend=Fout+S; }Tp inline void read(T& x){x=0; char ch; while (!isdigit(ch=tc()));while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));}Tp inline void write(T x){RI ptop=0; while (pt[++ptop]=x%10,x/=10);while (ptop) pc(pt[ptop--]+48); pc(' ');}inline void flush(void){fwrite(Fout,1,Ftop-Fout,stdout);}#undef tc#undef pc
}F;
struct Complex
{long double x,y;inline Complex(const long double& X=0,const long double& Y=0){x=X; y=Y;}friend inline Complex operator + (CC A,CC B){return Complex(A.x+B.x,A.y+B.y);}friend inline Complex operator - (CC A,CC B){return Complex(A.x-B.x,A.y-B.y);}friend inline Complex operator * (CC A,CC B){return Complex(A.x*B.x-A.y*B.y,A.x*B.y+A.y*B.x);}inline void operator /= (const long double& p){x/=p; y/=p;}
}A[N<<2]; int a[N<<2],ans[N<<2],fact[N],inv[N];
struct edge
{int to,nxt;
}e[N<<1]; int n,head[N],cnt,x,y,dis[N],lim;
class FFT_Solver
{private:static const int S=ceil(sqrt(mod)),SS=1LL*S*S%mod;int rev[N<<2],p;public:inline void init(CI n){for (lim=1,p=0;lim<=n;lim<<=1,++p);for (RI i=0;i<lim;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<p-1);}inline void FFT(Complex *f,CI opt){RI i; for (i=0;i<lim;++i) if (i<rev[i]) swap(f[i],f[rev[i]]);for (i=1;i<lim;i<<=1){Complex D(cos(pi/i),sin(pi/i)*opt);for (RI j=0;j<lim;j+=(i<<1)){Complex W(1,0); for (RI k=0;k<i;++k,W=W*D){Complex x=f[j+k],y=f[i+j+k]*W;f[j+k]=x+y; f[i+j+k]=x-y;}}}if (!~opt) for (i=0;i<lim;++i) f[i]/=lim;}inline void MTT(int *TA,int *TB,int *TC,CI n){static Complex A[N<<2],B[N<<2],C[N<<2],D[N<<2],E[N<<2],F[N<<2],G[N<<2],H[N<<2];RI i; for (init(n<<1),i=0;i<n;++i)A[i]=Complex(TA[i]/S),B[i]=Complex(TA[i]%S),C[i]=Complex(TB[i]/S),D[i]=Complex(TB[i]%S);for (FFT(A,1),FFT(B,1),FFT(C,1),FFT(D,1),i=0;i<lim;++i)E[i]=A[i]*C[i],F[i]=B[i]*C[i],G[i]=A[i]*D[i],H[i]=B[i]*D[i];for (FFT(E,-1),FFT(F,-1),FFT(G,-1),FFT(H,-1),i=0;i<lim;++i)TC[i]=(((LL)(E[i].x+0.5)%mod)*SS)%mod,(TC[i]+=(((LL)(F[i].x+0.5)%mod)*S)%mod)%=mod,(TC[i]+=(((LL)(G[i].x+0.5)%mod)*S)%mod)%=mod,(TC[i]+=(LL)(H[i].x+0.5)%mod)%=mod;}
}P;
#define to e[i].to
class Point_Divide_Solver
{private:int size[N],mx[N],num[N],rt,ats,mdp; bool vis[N];inline void maxer(int& x,CI y){if (y>x) x=y;}inline void getrt(CI now=1,CI fa=0){size[now]=1; mx[now]=0; for (RI i=head[now];i;i=e[i].nxt)if (to!=fa&&!vis[to]) getrt(to,now),size[now]+=size[to],maxer(mx[now],size[to]);if (maxer(mx[now],ats-size[now]),mx[now]<mx[rt]) rt=now;}inline void travel(CI now,CI fa=0,CI dep=0){maxer(mdp,dep); ++num[dep]; for (RI i=head[now];i;i=e[i].nxt)if (to!=fa&&!vis[to]) travel(to,now,dep+1);}inline void calc(CI opt){RI i; for (P.init(mdp<<1),i=0;i<=mdp;++i) A[i]=Complex(num[i],0);for (i=mdp+1;i<lim;++i) A[i]=Complex();for (P.FFT(A,1),i=0;i<lim;++i) A[i]=A[i]*A[i];for (P.FFT(A,-1),lim=min(n-1,mdp<<1),i=0;i<=lim;++i)dis[i]+=(LL)(A[i].x+0.5)%mod*opt,(dis[i]+=mod)%=mod;}inline void clear(void){for (RI i=0;i<=mdp;++i) num[i]=0;}inline void solve(CI now){RI i; mdp=0; travel(now); calc(1); clear(); vis[now]=1;for (i=head[now];i;i=e[i].nxt) if (!vis[to])mdp=0,travel(to,now,1),calc(-1),clear();for (i=head[now];i;i=e[i].nxt) if (!vis[to])mx[rt=0]=INF,ats=size[to],getrt(to,now),solve(rt);}public:inline void divide(void){mx[rt=0]=INF; ats=n; getrt(); solve(rt);}
}PD;
#undef to
inline void addedge(CI x,CI y)
{e[++cnt]=(edge){y,head[x]}; head[x]=cnt;e[++cnt]=(edge){x,head[y]}; head[y]=cnt;
}
inline int quick_pow(int x,int p=mod-2,int mul=1)
{for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline void init(void)
{RI i; for (fact[0]=i=1;i<=n;++i) fact[i]=1LL*fact[i-1]*i%mod;for (inv[n]=quick_pow(fact[n]),i=n-1;~i;--i) inv[i]=1LL*inv[i+1]*(i+1)%mod;for (i=0;i<n;++i) a[i]=1LL*fact[n-i-1]*dis[i]%mod;//for (i=0;i<n;++i) printf("%d ",a[i]); putchar('\n');//for (i=0;i<n;++i) printf("%d ",inv[i]); putchar('\n');
}
signed main()
{//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);RI i; for (F.read(n),i=1;i<n;++i) F.read(x),F.read(y),addedge(x,y);for (PD.divide(),init(),P.MTT(a,inv,ans,n),i=0;i<n;++i)ans[n-i-1]=1LL*ans[n-i-1]*inv[n-1]%mod*fact[n-i-1]%mod;for (i=0;i<n;++i) F.write(ans[n-i-1]); return F.flush(),0;
}

转载于:https://www.cnblogs.com/cjjsb/p/11285742.html

Codechef Chef Cuts Tree相关推荐

  1. CodeChef Chef and Digit Jumps 题解

    原题链接:Chef and Digit Jumps 题意:原题中有链接. 题解:一道很明显的bfs题,就是跳就可以了,当然,跳的时候可以加一些优化,具体看代码 #include <queue&g ...

  2. CodeChef Chef and Churu [分块]

    题意: 单点修改$a$ 询问$a$的区间和$f$的区间和 原来普通计算机是这道题改编的吧... 对$f$分块,预处理$c[i][j]$为块i中$a_j$出现几次,$O(NH(N))$,只要每个块差分加 ...

  3. linux ssh端口是什么意思,SSH是什么?Linux如何修改SSH端口号?

    数字对象NSNumber //将int类型转化成对象 ; NSNumber *numberString = [NSNumber numberWithInt:number]; //对象是可以放入数组的 ...

  4. 【模板】【洛谷P5487】—Berlekamp-Massey算法

    传送门 可以用来求解数列的最短常系数线性递推式 即一个长度为mmm的数列rrr满足对于i∈[m+1,n]i\in[m+1,n]i∈[m+1,n] 满足Ai=∑j=1mAi−jrjA_i=\sum_{j ...

  5. CFCC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries

    https://www.codechef.com/DEC17/problems/CHEFEXQ 题意: 位置i的数改为k 询问区间[1,i]内有多少个前缀的异或和为k 分块 sum[i][j] 表示第 ...

  6. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

  7. Codechef:Path Triples On Tree

    Path Triples On Tree 题意是求树上都不相交或者都相交的路径三元组数量. 发现blog里没什么树形dp题,也没有cc题,所以来丢一道cc上的树形dp题. 比较暴力,比较恶心 #inc ...

  8. 一二三系列之CodeChef分块——Chef and Churu,Chef and Problems,Children Trips

    文章目录 Chef and Churu source solution code Chef and Problems source solution code Children Trips sourc ...

  9. 【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair

    第一次写泰勒展开:本地和CC差距好大 题目大意 大厨住的城市里办了一场美食节.一条街上开设了$N$个摊位,编号为$1∼N$.这天开始时,第$i$个摊位的食物会导致食物中毒的概率是$P_i$.在这一天中 ...

最新文章

  1. 博科VP:闪存推动了与之相匹配的第六代FC的发展
  2. 现代计算机入门知识,计算机基础知识
  3. python中 time、datetime、random模块
  4. discrete mathematics important questions
  5. RGB_D_开发征程(使用Kinect)
  6. SQL Server 数据库关键知识点详解(优秀经典)
  7. ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX这些东东是什么鬼
  8. 内部矩阵维度必须一致simulink_深度学习/目标检测之numpy——向量和矩阵乘法相关...
  9. 专栏:谈谈我对当下大数据整顿的理解与风控建议
  10. 【Spring.net点滴】
  11. Mysql和Oracle如何计算QPS和TPS
  12. C Tricks(十三)—— trim 的实现
  13. IT项目经验和难点分享
  14. 华为算法精英赛(题1:判断输入天数为当年的第几天)
  15. ZigBee-CC2530单片机 - LED呼吸灯
  16. Radon变换实现对图像倾斜校正 matlab
  17. 测试方案包含哪些内容?
  18. 《炬丰科技-半导体工艺》Micro-LED 显示器量化生产关键技术
  19. 亮眼的PPT文字填充特效
  20. 生物信息学名词解释 | K-mer (长度为k的短序列)

热门文章

  1. 用Advanced Installer制作DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版详解
  2. Mindjet MindManagers思维导图使用记录
  3. 一致代码段与非一致代码段
  4. css3 text-shadow 为网页字体添加阴影
  5. 在windows下使用llvm+clang
  6. wince 6.0 设备管理器架构
  7. 安卓应用程序插件化开发框架 -AAP Framework
  8. muduo之mutex和condition
  9. linux中的fg命令
  10. 建立STM32的工程步骤(版本1)