codechef Prime Distance On Tree(树分治+FFT)
题目链接:http://www.codechef.com/problems/PRIMEDST/
题意:给出一棵树,边长度都是1。每次任意取出两个点(u,v),他们之间的长度为素数的概率为多大?
树分治,对于每个根出发记录边的长度出现几次,然后每次求卷积,用素数表查一下即可添加答案。
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<complex>
#define ll long long
#define N 150005
typedef std::complex<double> cd;
int mark[],p[];
int son[],F[],first[],next[],tot,go[];
int lc,n,sum,dis[],root,vis[],mxdis;
ll a[],b[],c[],A[],B[];
ll ans1=,ans2=;
int read(){
char ch=getchar();int t=,f=;
while (ch<''||ch>''){
if (ch=='-') f=-;
ch=getchar();
}
while (''<=ch&&ch<=''){
t=t*+ch-'';
ch=getchar();
}
return t*f;
}
int bitrev(int t,int n){
int res=;
for (int i=;i<n;i++) res|=((t>>(n-i-))&)<<i;//括号要多加
return res;
}
void fft(cd *a,int n,int rev){
int len=<<n;
static cd y[N];double Pi=acos(-);
for (int i=;i<len;i++) y[i]=a[bitrev(i,n)];
for (int d=;d<len;d<<=){
cd wn(exp(cd(,Pi*rev/d)));
for (int k=;k<len;k+=*d){
cd w(,);
for (int i=k;i<k+d;i++,w*=wn){
cd u=y[i],v=w*y[i+d];
y[i]=u+v;
y[i+d]=u-v;
}
}
}
if (rev==-)
for (int i=;i<len;i++) y[i]/=len;
for (int i=;i<len;i++) a[i]=y[i];
}
void mul(ll *a,int la,ll *b,int lb,ll *c,int &lc){
int len=,n=;
static cd t1[N],t2[N];
for (;len<la*||len<lb*;len<<=,n++);
for (int i=;i<la;i++) t1[i]=cd(a[i],);
for (int i=;i<lb;i++) t2[i]=cd(b[i],);
for (int i=la;i<len;i++) t1[i]=cd(,);
for (int i=lb;i<len;i++) t2[i]=cd(,);
fft(t1,n,);fft(t2,n,);
for (int i=;i<len;i++) t1[i]*=t2[i];
fft(t1,n,-);
for (int i=;i<len;i++) c[i]=(ll)(t1[i].real()+0.5);
lc=len;
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);
insert(y,x);
}
void prework(){
mark[]=mark[]=;
for (int i=;i<=;i++){
if (!mark[i]){
p[++p[]]=i;
}
for (int j=;j<=p[]&&p[j]*i<=;j++){
mark[p[j]*i]=;
if (i%p[j]==) break;
}
}
}
void findroot(int x,int fa){
son[x]=;
F[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]||pur==fa) continue;
findroot(pur,x);
son[x]+=son[pur];
F[x]=std::max(F[x],son[pur]);
}
F[x]=std::max(F[x],sum-son[x]);
if (F[x]<F[root]) root=x;
}
void pre(int x,int fa){
dis[x]=dis[fa]+;
mxdis=std::max(mxdis,dis[x]);
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa||vis[pur]) continue;
pre(pur,x);
}
}
void dfs(int x,int fa){
b[dis[x]]++;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa||vis[pur]) continue;
dis[pur]=dis[x]+;
dfs(pur,x);
}
}
void work(int x){
dis[]=-;mxdis=;
int all=sum;
pre(x,);
for (int i=;i<=mxdis+;i++) a[i]=b[i]=;
a[]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
dis[pur]=;
for (int j=;j<=mxdis;j++) b[j]=;
dfs(pur,x);
for (int j=;j<=mxdis;j++) A[j]=a[j],B[j]=b[j];
mul(A,mxdis+,B,mxdis+,c,lc);
int lim=std::min(mxdis*,);
for (int i=;i<=p[]&&p[i]<=lim;i++){
ans1+=c[p[i]];
}
for (int i=;i<=mxdis;i++)
a[i]+=b[i];
}
vis[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
if (son[pur]>son[x]) sum=all-son[x];
else sum=son[pur];
root=;
findroot(pur,x);
work(root);
}
}
int main(){
prework();
while (scanf("%d",&n)!=EOF){
if (n==) break;
tot=;
for (int i=;i<=n;i++) first[i]=vis[i]=;
for (int i=;i<n;i++){
int x,y;
x=read();y=read();
add(x,y);
}
root=;sum=n;
F[]=;
ans1=ans2=;
findroot(,);
work(root);
ans2=(ll)(((ll)n)*((ll)(n-))/);
double tmp=((double)(ans1))/((double)(ans2));
printf("%.8lf\n",tmp);
}
}
codechef Prime Distance On Tree(树分治+FFT)的更多相关文章
- CodeChef - PRIMEDST Prime Distance On Tree 树分治 + FFT
Prime Distance On Tree Problem description. You are given a tree. If we select 2 distinct nodes unif ...
- Codechef Prime Distance On Tree
[传送门] FFT第四题! 暑假的时候只会点分,然后合并是暴力合并的...水过去了... 其实两条路径长度的合并就是卷积的过程嘛,每次统计完路径就自卷积一下. 刚开始卷积固定了值域.T了.然后就不偷懒 ...
- prime distance on a tree(点分治+fft)
最裸的点分治+fft,调了好久,太菜了.... #include<iostream> #include<cstring> #include<cstdio> #inc ...
- POJ 1741 Tree 树分治
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...
- POJ 1741.Tree 树分治 树形dp 树上点对
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 24258 Accepted: 8062 Description ...
- poj 1744 tree 树分治
Tree Time Limit: 1000MS Memory Limit: 30000K Description Give a tree with n vertices,each ed ...
- 【BZOJ-1468】Tree 树分治
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1025 Solved: 534[Submit][Status][Discuss] ...
- HDU 4812 D Tree 树分治+逆元处理
D Tree Problem Description There is a skyscraping tree standing on the playground of Nanjing Unive ...
- HDU4670 Cube number on a tree 树分治
人生的第一道树分治,要是早点学我南京赛就不用那么挫了,树分治的思路其实很简单,就是对子树找到一个重心(Centroid),实现重心分解,然后递归的解决分开后的树的子问题,关键是合并,当要合并跨过重心的 ...
随机推荐
- Codeforces 335B Palindrome
http://codeforces.com/contest/335/problem/B 题意: 给定一个长度不超过5*10^4的只包含小写字母的字符串,要求你求它的回文子序列,如果存在长度为100的 ...
- 函数call相关[ASM]
前言: __cdecl:C/C++函数默认调用约定,参数依次从右向左传递,并压入堆栈,最后由调用函数清空堆栈,这种方式适用于传递参数个数可变的被调用函数,只有被调用函数才知道它传递了多少个参数给被 ...
- Android中实现全屏、无标题栏的两种办法(另附Android系统自带样式的解释)
在进行UI设计时,我们经常需要将屏幕设置成无标题栏或者全屏.要实现起来也非常简单,主要有两种方法:配置xml文件和编写代码设置. 1.在xml文件中进行配置 在项目的清单文件AndroidManife ...
- 鼠标键盘无法进入:(EE) config/hal: couldn’t initialise context: (null)
vi /var/log/Xorg.0.log 发现有一行:(EE) config/hal: couldn’t initialise context: (null) 在xorg.conf里面加上下面选项 ...
- Linux企业级项目实践之网络爬虫(13)——处理user-agent
User Agent即用户代理,是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA.它是一个特殊字符串头,是一种向访问网站提供你所使用的浏览器类型及版本.操作系统及版本.浏览 ...
- eclipse,tomcat部署web项目,以及本地文件访问
1.直接把项目复制到Tomcat安装目录的webapps目录中,这是最简单的一种Tomcat项目部署的方法,也是初学者最常用的方法. 2.在tomcat安装目录中有一个conf文件夹,打开此文件夹,其 ...
- SVN 一次性提交多个目录中文件
情况一:将项目中未加入版本控制的文件提交到版本库. 在使用WINDOW下的SVN客户端工具时,在提交一个项目的文件时,如果有未加入版本库的文件,这时可以先将未加入的文件选中,然后一起提交. 但在LIN ...
- Oracle11gRAC安装
安装Oracle RAC 一.硬件环境 ①用虚拟机搭建两台机器,操作系统都为: [root@node1 ~]# cat /etc/issue Red Hat Enterprise Linux Serv ...
- animation之translate、scale、alpha、rotate动画效果呈现
动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面 ...
- nyist 82迷宫寻宝(一)(BFS)
题目连接:http://acm.nyist.net/JudgeOnline/problem.php?pid=82 此题在基础BFS上加入了门和钥匙,要找齐所有钥匙才能开门,所以要对门特殊处理. 1.先 ...