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. hdu2051

    二进制转换 #include <stdio.h> void change(int n){ ]; ; while(n){ num[cnt]=n%; n/=; cnt++; } cnt--; ...

  2. redis介绍和安装和主从介绍(二)

    redis正式安装过程 安装依赖,下载解压,编译安装 yum install gcc-c++ tcl wget http://download.redis.io/releases/redis-4.0. ...

  3. 洛谷P2351 [SDOi2012]吊灯 【数学】

    题目 Alice家里有一盏很大的吊灯.所谓吊灯,就是由很多个灯泡组成.只有一个灯泡是挂在天花板上的,剩下的灯泡都是挂在其他的灯泡上的.也就是说,整个吊灯实际上类似于[b]一棵树[/b].其中编号为 1 ...

  4. 对拍程序(Win)

    代码如下: @echo off :again rand.exe echo "rand finish" asd.exe echo "1.exe finish" 未 ...

  5. 深入了解类加载过程及Java程序执行顺序

    前言 在Java中,静态 Static关键字使用十分常见 本文全面 & 详细解析静态 Static关键字,希望你们会喜欢 目录 1. 定义 一种 表示静态属性的 关键字 / 修饰符 2. 作用 ...

  6. BZOJ 1226 [SDOI2009]学校食堂Dining ——状压DP

    看到B<=8,直接状态压缩即可. dp[i][j][k]表示当前相对位置是关于i的,并且i以前的已经就餐完毕,j表示i和之后的就餐情况,k表示上一个就餐的人的相对位置. 然后Dp即可 #incl ...

  7. BZOJ4446 [Scoi2015]小凸玩密室 【树形Dp】

    题目 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要花费,之后每点亮4 ...

  8. [NOI2001] 食物链 (扩展域并查集)

    题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...

  9. UVa10234 Race

    递推,设有i个人排在第一名,剩下的人排在后面,方案有f[i]种,则f[i]=sum(c[n][i]*f[n-i]) 1<=i<=n /*by SilverN*/ #include<a ...

  10. 标准C程序设计七---23

    Linux应用             编程深入            语言编程 标准C程序设计七---经典C11程序设计    以下内容为阅读:    <标准C程序设计>(第7版) 作者 ...