Prime Distance On Tree

Problem description.

You are given a tree. If we select 2 distinct nodes uniformly at random, what's the probability that the distance between these 2 nodes is a prime number?

Input

The first line contains a number N: the number of nodes in this tree.
The following N-1 lines contain pairs a[i] and b[i], which means there is an edge with length 1 between a[i] and b[i].

Output

Output a real number denote the probability we want.
You'll get accept if the difference between your answer and standard answer is no more than 10^-6.

Constraints

2 ≤ N ≤ 50,000

The input must be a tree.

Example

Input:
5
1 2
2 3
3 4
4 5 Output:
0.5

Explanation

We have C(5, 2) = 10 choices, and these 5 of them have a prime distance:

1-3, 2-4, 3-5: 2

1-4, 2-5: 3

Note that 1 is not a prime number.

题意:

    给你一颗树,n个点,n-1条边

    让你求任意选两个不同的点,其距离是素数的概率

题解:

    点分治

    求出只经过重心的所有路径深度种类数

    让属于不同的子树的点,利用其深度进行任意组合(FFT加速)求出最后组合结果

    累积是素数的答案即可,复杂度 n* logn * logn

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
typedef unsigned long long ULL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 3e5+, M = 1e6+, mod = 1e9+,inf = 2e9; struct Complex {
double r , i ;
Complex () {}
Complex ( double r , double i ) : r ( r ) , i ( i ) {}
Complex operator + ( const Complex& t ) const {
return Complex ( r + t.r , i + t.i ) ;
}
Complex operator - ( const Complex& t ) const {
return Complex ( r - t.r , i - t.i ) ;
}
Complex operator * ( const Complex& t ) const {
return Complex ( r * t.r - i * t.i , r * t.i + i * t.r ) ;
}
} ; void FFT ( Complex y[] , int n , int rev ) {
for ( int i = , j , t , k ; i < n ; ++ i ) {
for ( j = , t = i , k = n >> ; k ; k >>= , t >>= ) j = j << | t & ;
if ( i < j ) swap ( y[i] , y[j] ) ;
}
for ( int s = , ds = ; s <= n ; ds = s , s <<= ) {
Complex wn = Complex ( cos ( rev * * pi / s ) , sin ( rev * * pi / s ) ) , w ( , ) , t ;
for ( int k = ; k < ds ; ++ k , w = w * wn ) {
for ( int i = k ; i < n ; i += s ) {
y[i + ds] = y[i] - ( t = w * y[i + ds] ) ;
y[i] = y[i] + t ;
}
}
}
if ( rev == - ) for ( int i = ; i < n ; ++ i ) y[i].r /= n ;
}
Complex s[N],t[N]; int vis[N],f[N],siz[N],n,allnode,root;
int P[N];
vector<int > G[N];
void init() {
for(int i = ; i <= *n; ++i) {
if(!P[i]) {
for(int j = i+i; j <= *n; j += i)
P[j] = ;
}
}
P[] = ;
for(int i = ; i <= n; ++i) vis[i] = ;
}
void getroot(int u,int fa) {
f[u] = ;
siz[u] = ;
for(int i = ; i < G[u].size(); ++i) {
int to = G[u][i];
if(vis[to] || to == fa) continue;
getroot(to,u);
siz[u] += siz[to];
f[u] = max(f[u],siz[to]);
}
f[u] = max(f[u], allnode - siz[u]);
if(f[u] < f[root]) root = u;
} int len = ,cnt[N],dep[N],nowcnt[N],mxdep;
LL ans = ;
void getdeep(int u,int f) {
siz[u] = ;
for(int i = ; i < G[u].size(); ++i) {
int to = G[u][i];
if(vis[to] || to == f) continue;
dep[to] = dep[u] + ;
getdeep(to,u);
mxdep = max(mxdep,dep[to]);
siz[u] += siz[to];
}
}
void dfs(int u,int f,int p) {
nowcnt[dep[u]]+=p;
if(p == -) cnt[dep[u]] += ;
for(int i = ; i < G[u].size(); ++i) {
int to = G[u][i];
if(vis[to] || to == f) continue;
dfs(to,u,p);
}
}
LL cal(int u) {
LL ret = ;
for(int i = ; i <= n; ++i) cnt[i] = ;
cnt[] = ;
dep[u] = ;
mxdep = -;
getdeep(u,);
len = ;
while(len <= *mxdep) len<<=;
for(int i = ; i < G[u].size(); ++i) {
int to = G[u][i];
if(vis[to]) continue;
dfs(to,u,);
for(int j = ; j < len; ++j) t[j] = Complex(nowcnt[j],);
for(int j = ; j < len; ++j) s[j] = Complex(cnt[j],); FFT(s,len,);FFT(t,len,);
for(int j = ; j < len; ++j) s[j] = s[j] * t[j];
FFT(s,len,-);
for(int j = ;j < len; ++j) {
LL tmp = (s[j].r+0.5); if(P[j]) continue; ret += tmp;
}
dfs(to,u,-);
}
return ret;
}
void work(int u) {
vis[u] = ;
ans += cal(u);
// exit(0);
for(int i = ; i < G[u].size(); ++i) {
int to = G[u][i];
if(vis[to]) continue;
allnode = siz[to];
root = ;
getroot(to,);
work(root);
}
}
int main() {
scanf("%d",&n);
while(len <= n) len<<=;
init();
for(int i = ; i < n; ++i) {
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
} ans = ;
f[] = inf;root = ;allnode = n;
getroot(,);
work(root);
printf("%.6f\n",(double)1.0*ans/((double)n*(n-)/));
return ;
}

    

CodeChef - PRIMEDST Prime Distance On Tree 树分治 + FFT的更多相关文章

  1. 【CodeChef】Prime Distance On Tree

    vjudge 给定一棵边长都是\(1\)的树,求有多少条路径长度为质数 树上路径自然是点分治去搞,但是发现要求是长度为质数,总不能对每一个质数都判断一遍吧 自然是不行的,这个东西显然是一个卷积,我们合 ...

  2. codechef Prime Distance On Tree(树分治+FFT)

    题目链接:http://www.codechef.com/problems/PRIMEDST/ 题意:给出一棵树,边长度都是1.每次任意取出两个点(u,v),他们之间的长度为素数的概率为多大? 树分治 ...

  3. prime distance on a tree(点分治+fft)

    最裸的点分治+fft,调了好久,太菜了.... #include<iostream> #include<cstring> #include<cstdio> #inc ...

  4. POJ 1741 Tree 树分治

    Tree     Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...

  5. POJ 1741.Tree 树分治 树形dp 树上点对

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 24258   Accepted: 8062 Description ...

  6. poj 1744 tree 树分治

    Tree Time Limit: 1000MS   Memory Limit: 30000K       Description Give a tree with n vertices,each ed ...

  7. 【BZOJ-1468】Tree 树分治

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] ...

  8. HDU 4812 D Tree 树分治+逆元处理

    D Tree Problem Description   There is a skyscraping tree standing on the playground of Nanjing Unive ...

  9. HDU4670 Cube number on a tree 树分治

    人生的第一道树分治,要是早点学我南京赛就不用那么挫了,树分治的思路其实很简单,就是对子树找到一个重心(Centroid),实现重心分解,然后递归的解决分开后的树的子问题,关键是合并,当要合并跨过重心的 ...

随机推荐

  1. mysqlbinlog备份和mysqldump备份

    -bash : mysqldump: command not found -bash : mysqlbinlog:command not found 首先得知道mysql命令或mysqldump命令的 ...

  2. Python之转换py文件为无需依赖python环境的exe文件的方法

    在日常工作中,使用python脚本开发快速敏捷,但是其代码是可见的,而且充分的依赖python开发环境.为了达到保护我们源码的目的,或者不依赖python开发环境使用python脚本,将其转换成可以直 ...

  3. django-Ajax发送POST请求-csrf跨站请求的三种方式

    第一种 <script> $(".eq").on("click",function () { $.ajax({ url:"/eq/&quo ...

  4. c++ primer note

    ---恢复内容开始--- 1.decltype 2.auto 3.cbegin 4.cend 5.constexpr 6.(*Parray)[10]=&arr; //Parray 指向一个含有 ...

  5. win8激活工具,win 8激活工具,windows8激活工具,赶紧来下载咯

    同事前几天买了一个电脑,装的win8的系统,由于装office,需要激活,找了下office的激活工具,那个Office激活工具自带有win8激活,同事点错了,把正版系统给激活了,变成盗版了(悲剧.. ...

  6. MongoDB_java连接MongoDB

    java程序连接单机版的mongodb: 参考:http://www.runoob.com/mongodb/mongodb-java.html https://www.yiibai.com/mongo ...

  7. SQLite数据库相关操作

    一.创建数据库 这里创建了note便签数据表,字段有noteId.noteTitle.noteTime.noteInfo );  // TODO Auto-generated constructor ...

  8. ci框架——修改分页的显示样式

    修改ci框架分页的显示样式 用过ci框架的都知道,ci框架自带的分页样式是1,2下一页,在最开始刷新页面现实的时候如果页面不够多的话,那么首页和末页是不显的,这是ci框架的一个缺点, 这个时候需要我们 ...

  9. jquery知识汇总

    jQuery 选择器 选择器                  实例                                   选取 *                          $ ...

  10. jquery.fullPage.js全屏滚动插件

    注:本文内容复制于http://www.51xuediannao.com/js/jquery/jquery.fullPage.html 和 http://www.360doc.com/content/ ...