bzoj3451/Tyvj1953:Normal(点分治+FFT)
来源:互联网 发布:淘宝卖家怎么催快递 编辑:程序博客网 时间:2024/05/17 22:13
题面
题意:给你一棵树,XJB选点来做点分治,问期望的复杂度。
根据我对期望的粗鄙理解,期望就是个积分,所以它满足积分加减等线性运算。故这里可以考虑对每个点求期望复杂度。
对于点x,它产生的期望就是x在点分树中的期望深度。
再次运用期望的线性性质,我们可以对于每个y,求出x在y子树中的概率,由此推出期望。
经过小小的分析,发现x在y的子树中,仅当在x-y的路径上,y被第一个选中来分治,则概率为
然后原问题的答案为
若dis(i,j)不在分母里,就是一个果的点分治了。
我们换下枚举的顺序,设f[x]为距离为x的点对数,变成
同样考虑点分治,找到重心x,考虑过x的路径。
对于每个连通块。求出它们每个点到x的距离,设g[i]为到x距离为i的点数。我们发现两个g能对答案的贡献是个卷积的形式,用fft优化即可。
期望复杂度O(
比如说这样
用一条长链把fft的次数界撑大了,然后用大大的次数界不断地做fft。
应该先做深度小的连通块,再做深度大的。
#include <iostream>#include <fstream>#include <algorithm>#include <cmath>#include <ctime>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define mmst(a, b) memset(a, b, sizeof(a))#define mmcp(a, b) memcpy(a, b, sizeof(b))typedef long long LL;const int N=60060,oo=1e9+7;const LL g=3,p=1004535809;int n,rev[N];int nn;int to[N],nex[N],head[N],cnt;int root,sum,siz[N],d[N],dep[N],len,slen;LL a[N],b[N],c[N],ans[N];double res=0.0;bool vis[N];void read(int &hy){ hy=0; char cc=getchar(); while(cc<'0'||cc>'9') cc=getchar(); while(cc>='0'&&cc<='9') { hy=(hy<<3)+(hy<<1)+cc-'0'; cc=getchar(); }}LL cheng(LL a,LL b){ LL res=1ll; for(;b;b>>=1,a=a*a%p) if(b&1) res=res*a%p; return res;}void init(int lim){ int k=-1; n=1; while(n<lim) n<<=1,k++; for(int i=0;i<n;i++) rev[i]=(rev[i>>1] >> 1) | ((i&1)<<k);}void ntt(LL *a,int ops){ for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]); for(int l=2;l<=n;l<<=1) { int m=l>>1; LL wn; if(ops) wn=cheng(g,(p-1)/l); else wn=cheng(g,p-1-(p-1)/l); for(int i=0;i<n;i+=l) { LL w=1ll; for(int k=0;k<m;k++) { LL t=a[i+k+m]*w%p; a[i+k+m]=(a[i+k]-t+p)%p; a[i+k]=(a[i+k]+t)%p; w=w*wn%p; } } } if(!ops) { LL Inv=cheng(n,p-2); for(int i=0;i<n;i++) a[i]=a[i]*Inv%p; }}void add(int u,int v){ to[++cnt]=v; nex[cnt]=head[u]; head[u]=cnt;}void dfsRoot(int x,int fa){ d[x]=0; siz[x]=1; for(int h=head[x];h;h=nex[h]) if(!vis[to[h]]&&to[h]!=fa) { dfsRoot(to[h],x); siz[x]+=siz[to[h]]; d[x]=max(d[x],siz[to[h]]); } d[x]=max(d[x],sum-siz[x]); if(d[x]<d[root]) root=x;}void dfsLen(int x,int fa){ len=max(len,dep[x]); a[dep[x]]++; for(int h=head[x];h;h=nex[h]) if(!vis[to[h]]&&to[h]!=fa) { dep[to[h]]=dep[x]+1; dfsLen(to[h],x); }}void dfsSol(int x){ vis[x]=1; slen=1; b[0]=1; for(int h=head[x];h;h=nex[h]) if(!vis[to[h]]) { len=0; dep[to[h]]=1; dfsLen(to[h],0); init(len+slen+1); for(int i=0;i<n;i++) c[i]=b[i]; for(int i=0;i<=len;i++) b[i]+=a[i]; ntt(c,1); ntt(a,1); for(int i=0;i<n;i++) c[i]=c[i]*a[i]%p; ntt(c,0); for(int i=0;i<n;i++) ans[i]+=c[i]; for(int i=0;i<n;i++) a[i]=0; slen=max(slen,len); } for(int i=0;i<=slen;i++) b[i]=0; for(int h=head[x];h;h=nex[h]) if(!vis[to[h]]) { root=0; sum=siz[to[h]]; dfsRoot(to[h],0); dfsSol(root); }}int main(){ cin>>nn; for(int i=1;i<nn;i++) { int u,v; read(u); read(v); u++; v++; add(u,v); add(v,u); } sum=nn; root=0; d[0]=oo; dfsRoot(1,0); dfsSol(root); for(int i=1;i<nn;i++) res+=2.0*ans[i]/(i+1); res+=nn; printf("%.4lf\n",res);}
阅读全文
0 0
- bzoj3451/Tyvj1953:Normal(点分治+FFT)
- Tyvj1953:Normal (点分治+FFT)
- BZOJ3451 Normal 点分治+FFT
- BZOJ3451 Tyvj1953 Normal
- [bzoj3451]Tyvj1953 Normal
- 【bzoj3451】【Tyvj1953】Normal 题解
- [BZOJ3451][Tyvj1953]Normal
- bzoj 3451: Tyvj1953 Normal
- CodeChef PrimeDST【点分治】【FFT】
- CC PRIMEDST(点分治+FFT)
- bzoj3451
- CC Prime Distance On Tree (树的点分治 + FFT)
- Codechef Prime Distance On Tree(点分治+FFT)
- 素数路径 Prime Distance On Tree 点分治+FFT
- 解题报告:Prime Distance On Tree 点分治 + FFT
- BZOJ3456:城市规划(EGF+FFT/CDQ分治+FFT)
- 树分治(点分治+边分治)
- HDU 5730 Shell Necklace(FFT+分治)
- io流 拷贝
- linkedList三行代码实现浏览记录显示
- 【2017.9.29】register、宏定义、fork函数、C源程序
- [2017.9.23-24]JAVA数据类型&基础语法&运算符&键盘录入
- C语言小碎片三
- bzoj3451/Tyvj1953:Normal(点分治+FFT)
- Python 嵌套列表的排序(匿名函数lambda)
- bzoj 3993: [SDOI2015]星际战争
- solr进阶七:与jQuery结合的自动补全功能
- 中缀 前缀 后缀表达式 相互转换
- Java编程思想读书笔记——初始化与清理(二)
- Ajax总结
- KMP算法求模式串在原串中出现的次数
- linux下ssh服务器安装与登录