CodeChef - PRIMEDST Prime Distance On Tree 树分治 + FFT
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的更多相关文章
- 【CodeChef】Prime Distance On Tree
vjudge 给定一棵边长都是\(1\)的树,求有多少条路径长度为质数 树上路径自然是点分治去搞,但是发现要求是长度为质数,总不能对每一个质数都判断一遍吧 自然是不行的,这个东西显然是一个卷积,我们合 ...
- codechef Prime Distance On Tree(树分治+FFT)
题目链接:http://www.codechef.com/problems/PRIMEDST/ 题意:给出一棵树,边长度都是1.每次任意取出两个点(u,v),他们之间的长度为素数的概率为多大? 树分治 ...
- 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),实现重心分解,然后递归的解决分开后的树的子问题,关键是合并,当要合并跨过重心的 ...
随机推荐
- hlg 1580 tell me the length
智力题,观察上一行,有几个数字. 比如,S[1]=1; S[2]=11; S[3]=21; S[4]=1211; 这样就可以观察出来,序列一是1个1 ---> S[2] = 11 ; 序列二是 ...
- 微软.net一些类的源码
地址:http://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs 关键字:refer ...
- RESTful API接口
我所理解的RESTful Web API [设计篇] 百度:RESTful restful一种软件架构风格.设计风格,而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件 ...
- 九度oj 题目1340:小A的计算器
题目描述: 以往的操作系统内部的数据表示都是二进制方式,小A新写了一个操作系统,系统内部的数据表示为26进制,其中0-25分别由a-z表示. 现在小A要在这个操作系统上实现一个计算器,这个计算器要能实 ...
- [BZOJ1576] [Usaco2009 Jan]安全路经Travel(堆优化dijk + (并查集 || 树剖))
传送门 蒟蒻我原本还想着跑两边spfa,发现不行,就gg了. 首先这道题卡spfa,所以需要用堆优化的dijkstra求出最短路径 因为题目中说了,保证最短路径有且只有一条,所以可以通过dfs求出最短 ...
- python 写excal
workbook.save(filename)
- java 数据库连接的几个步骤
Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@你的主 ...
- nosql整理
Nosql: Redis,Memcache,MongoDB,Hbase,Couchbase LevelDB https://www.cnblogs.com/lina520/p/7919551.htm ...
- elasticsearch起步
elasticsearch教程 elastic入门教程 阮一峰的elasticsearch教程 elasticsearch官网 kibana用户手册 elasticsearch安装步骤 参考:http ...
- POJ 2125 最小点权覆盖集(输出方案)
题意:给一个图(有自回路,重边),要去掉所有边,规则:对某个点,可以有2种操作:去掉进入该点 的所有边,也可以去掉出该点所有边,(第一种代价为w+,第二种代价为w-).求最小代价去除所有边. 己思:点 ...